# TrendTrack API Documentation > Full plaintext documentation for the TrendTrack public API. Intended to be ingested by LLM agents in a single request — no scraping, no chunking. --- # Authentication Source: https://docs.trendtrack.io/docs/guides/authentication ## Authorization header Authenticate every request with a workspace API key using the `Authorization` header. ```http Authorization: Bearer ``` ## What Trendtrack validates - Whether the API key is valid and active - Whether the bound workspace currently has Public API access - Whether the credential has been revoked or expired - Workspace-level authorization and delegated user state ## Recommended verification flow 1. Create the key in the workspace API settings UI. 2. Call `GET /v1/me` to confirm the resolved credential and request flow. 3. Call `GET /v1/workspace` to verify the bound workspace context. --- # Boards Source: https://docs.trendtrack.io/docs/guides/boards Boards are where Trendtrack users save what they find. The `/v1/boards` endpoints read and write the same boards as the web app and the browser extension: an item added through the API shows up in the app, and the reverse. The `/v1/favorites/*` endpoints are deprecated. They are a compatibility layer over boards: favorite folder ids are board ids, saved favorite ids are board item ids. New integrations should use `/v1/boards`. ## Collections and folders Every board has a `kind`: | Kind | Holds | `surface` | | ------------ | ------------------------------------------------------------------ | -------------------------------------------------------------------------- | | `collection` | Any saved content, mixed. This is the default. | Always `null`. | | `folder` | One kind of content only, set by its `surface`. | Required: `ads`, `shops`, `landing`, `emails`, `products`, `advertisers`. | Boards nest: a board's children have the same `kind` as their parent (collections in collections, folders in folders). A child also takes its parent's visibility. Breaking either rule returns `409 conflict` with `details.reason = "board_hierarchy_conflict"`. Adding content to a folder of another surface — a shop into an `ads` folder — returns `409 conflict` with `details.reason = "surface_mismatch"` and the expected and actual surfaces. ## Who can see and change a board `visibility` is `private` (its creator and the people it is shared with), `workspace` (the whole workspace), or `public` (readable by any Trendtrack user who has its id). - **API keys** act for the workspace. They only reach `workspace` boards, and boards they create are `workspace` boards. - **Delegated credentials** (a user connected through OAuth, for example in Claude or ChatGPT) act as that user. They create `private` boards by default and can list them with `scope=personal`. - Workspace boards need a Business or Agency plan with team seats. Boards in general need a Pro, Business, or Agency plan; otherwise the API returns `403 product_entitlement_required`. - Every write needs a credential allowed to change workspace content. Each board also returns `capabilities.canAddItems` and `capabilities.canManage` for the current credential: check them before writing. ## Save an item ```bash title="Find a board, then save an ad into it" export TT_API_BASE_URL="https://api.trendtrack.io" curl -s "$TT_API_BASE_URL/v1/boards?rootOnly=true&limit=100" \ -H "Authorization: Bearer $TT_API_KEY" curl -s -X POST "$TT_API_BASE_URL/v1/boards/$BOARD_ID/items" \ -H "Authorization: Bearer $TT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sourceType": "meta_ad", "sourceId": "facebook_1089760056243476"}' ``` `sourceId` must be the id the matching endpoint returns: | `sourceType` | `sourceId` | | ------------- | ------------------------------------------------------------------- | | `meta_ad` | Ad id from `/v1/ads*`: `facebook_` (bare digits accepted). | | `google_ad` | `google_CR` (`CR` accepted). | | `tiktok` | `tiktok_` (bare digits accepted). | | `shop` | The shop UUID from `/v1/shops*`, not its domain. | | `email` | `email:` (the bare email number is accepted). | | `advertiser` | The numeric Facebook page id. | Saving an item that is already in the board does not duplicate it: the response has `created: false` and costs no credit. ## Read a board `GET /v1/boards/{boardId}/items` returns references (`source.sourceType`, `source.sourceId`, position, who added it), not the content itself. Fetch the details you need from the resource endpoints, for example `GET /v1/ads/{adId}` or `GET /v1/shops/{shopId}`. ## Organize and share | Action | Endpoint | | -------------------------- | -------------------------------------------------- | | Rename, describe, change visibility | `PATCH /v1/boards/{boardId}` | | Move under another board | `PATCH /v1/boards/{boardId}/parent` with `{"parentBoardId": "..."}`; `null` moves it to the top level | | Move an item | `POST /v1/boards/{boardId}/items/{itemId}/move` with `targetBoardId` and an optional `position` | | Remove an item | `DELETE /v1/boards/{boardId}/items/{itemId}` | | Archive a board | `DELETE /v1/boards/{boardId}` — archives the board and everything under it | | Restore it | `POST /v1/boards/{boardId}/restore`; list archived boards with `state=archived` | | Share it | `POST /v1/boards/{boardId}/share-links` — each call creates a new link | Archiving is reversible; nothing is deleted. ## Credits | Call | Cost | | -------------------------------------- | -------------------------------------- | | `GET /v1/boards`, `GET .../items` | 1 credit per returned row | | `GET /v1/boards/{boardId}` | 1 credit | | Add an item | 1 credit, 0 when it was already there | | Remove an item | 1 credit, 0 when it was not there | | Any other write | 1 credit | --- # Credits & Billing Source: https://docs.trendtrack.io/docs/guides/credits-and-billing ## Credits model - Public API billing is credits-only. - Metered endpoints charge per returned row (or per call for single-resource endpoints), at the rate of the resource family below. - Every active workspace plan includes 10,000 recurring credits per month. - Top-up credits carry over and do not expire. ## Cost per endpoint The rate applies to each returned row, then the request total is rounded to the nearest whole credit. A query that returns 20 shops costs 80 credits; one that returns 3 ads costs 5. Requests that return nothing or fail cost nothing. | Resource family | Credits per row or call | REST endpoints | MCP tools | | --- | --- | --- | --- | | Shops & products | 4 | `/v1/shops`, `/v1/shops/query`, `/v1/shops/{shopId}` and its `products`, `advertisers`, `socials/history`, `sales/history`, `similar`; `/v1/products`, `/v1/products/query`, `/v1/products/{productId}`, `/v1/products/lookup`; `/v1/shops/image-search`, `/v1/products/image-search` | `search_shops`, `find_similar_shops`, `search_shops_by_image`, `search_products_by_image`, `search_products`, `get_product`, `product_launch_radar` | | Advertisers | 3 | `/v1/advertisers`, `/v1/advertisers/query`, `/v1/advertisers/{advertiserId}` and its `ads` | `search_advertisers` | | Emails | 2 | `/v1/emails/query`, `/v1/emails/{emailId}`, `/v1/emails/{emailId}/html`, `/v1/shops/{shopId}/emails`, `/v1/shops/{shopId}/emails/stats` | `search_emails`, `get_email_html`, `analyze_shop_emails` | | Meta ads | 1.5 | `/v1/ads`, `/v1/ads/query`, `/v1/ads/{adId}` and its `media-url`, `reach-history`, `share`; `/v1/ads/facets/landing-pages`; `/v1/products/{productId}/ads` | `search_ads`, `scan_ad`, `get_product_ads`, `create_ad_share_link`, `delete_ad_share_link` | | Everything else | 1 | Brandtrackers and their insights, workspace insights, boards, favorites, Google Ads, TikTok library, product share links | Brandtracker tools, boards tools, `find_winning_products`, `search_google_ads_library`, `search_tiktok_library`, `brief_competitor`, `daily_radar`, `analyze_product`, `create_product_share_link` | | Free | 0 | `/v1/lookup`, `/v1/facets/*`, `/v1/google-ads/facets/*`, `/v1/products/facets`, `/v1/brandtrackers/folders`, `/v1/me`, `/v1/workspace`, `/v1/workspace/folders`, `/v1/usage` | `lookup`, `lookup_filter_ids`, `check_credits`, `usage_get` | REST and MCP charge the same rate. Workspaces still on the legacy API add-on (pricing before August 2026) pay 1 credit per row on REST and 1.5 on MCP, whatever the endpoint. ## Consumption order 1. Recurring monthly credits are consumed first. 2. Top-up carry-over credits are consumed second. Metered collection endpoints use reservation and settlement in the backend, so the final cost is based on returned results rather than requested limits alone. ## Helpful endpoints and headers - `GET /v1/usage` exposes the runtime balance snapshot. It is unmetered, but still returns `X-Usage-Cost: 0`, `X-Credits-Used: 0`, and `X-Credits-Remaining`. - Successful metered responses can include `X-Usage-Cost`, `X-Credits-Used`, `X-Credits-Remaining`, and `X-Credits-Source`. - Shell endpoints like `/v1/me`, `/v1/workspace`, `/v1/openapi.json`, and `/v1/docs` remain unmetered. ## Response headers explained | Header | Meaning | Example value | | --------------------- | ------------------------------------------------------------------------------------ | ------------------------------ | | `X-Usage-Cost` | Credits consumed by this specific request. `/v1/usage` returns `0`. | `12` | | `X-Credits-Used` | Credits consumed by this specific request. `/v1/usage` returns `0`. | `12` | | `X-Credits-Remaining` | Balance after this request settled. Watch it to stop a loop before you run out. | `9872` | | `X-Credits-Source` | Bucket the credits were drawn from on metered calls. | `recurring`, `topup`, `hybrid` | | `X-Request-Id` | Stable per-request identifier echoed in error bodies. Quote when contacting support. | `req_01HZ…` | Metering headers are emitted on metered endpoints. `GET /v1/usage` is the unmetered exception: it returns `X-Usage-Cost: 0`, `X-Credits-Used: 0`, and `X-Credits-Remaining` so agents can read the balance from headers as well as the body. ## Poll `/v1/usage` at session start Long-running agents should call `/v1/usage` once when they boot to size their work against the remaining budget. It is unmetered, so there is no cost to calling it at every cold start. The response includes `X-Usage-Cost: 0`, `X-Credits-Used: 0`, and `X-Credits-Remaining`. ```bash title="Shell" export TT_API_BASE_URL="https://api.trendtrack.io" curl -s "$TT_API_BASE_URL/v1/usage" \ -H "Authorization: Bearer $TT_API_KEY" ``` ```json title="Response" { "data": { "plan": "professional", "monthly": { "included": 10000, "remaining": 7240, "resetAt": "2026-05-01T00:00:00.000Z" }, "topUp": { "remaining": 1500 }, "total": { "remaining": 8740 } }, "requestId": "req_01HZ…" } ``` If `total.remaining` is below your worst-case job cost, stop and surface the budget gap to the caller instead of hitting `402 insufficient_credits` mid-loop. ## Top-ups Manual and automatic top-ups are supported from the webapp billing layer. The fixed exchange rate is **$1 = 1,000 credits**, with a minimum top-up amount of **$10**. ## Force a docs cache refresh When the API schema or guides change, the `/docs/llms.txt` and `/docs/llms-full.txt` endpoints are cached for 1 hour. Call `GET /docs/invalidate` to purge the cache immediately (provide the `DOCS_INVALIDATE_SECRET` in production via `Authorization: Bearer …` or `?secret=…`). This endpoint is a maintenance helper — it is not part of the public API surface. --- # Errors Source: https://docs.trendtrack.io/docs/guides/errors ## Stable error envelope ```json { "error": { "code": "missing_api_key", "message": "Missing API key.", "requestId": "req_123" } } ``` Expect a stable JSON envelope and use the error code for logic, not the human message alone. ## Common public error codes - `missing_api_key` - `invalid_api_key` - `credential_not_found` - `credential_revoked` - `credential_expired` - `workspace_public_api_disabled` - `workspace_public_api_suspended` - `forbidden` - `rate_limited` - `insufficient_credits` - `internal_error` ## Status code guidance - **401**: missing or invalid authentication - **402**: insufficient credits for the requested work - **403**: authenticated but not allowed - **404**: the requested resource was not found - **429**: rate limited; check `Retry-After` ## Error code reference | `error.code` | HTTP | Retry? | What to do | |---|---|---|---| | `missing_api_key` | 401 | No | Set `Authorization: Bearer ` on the request. | | `invalid_api_key` | 401 | No | Re-copy the key from workspace settings — watch for whitespace or `x-api-key` confusion. | | `credential_not_found` | 401 | No | The key was deleted. Issue a new one. | | `credential_revoked` | 401 | No | The key was rotated. Issue a new one. | | `credential_expired` | 401 | No | Renew the key from workspace settings. | | `workspace_public_api_disabled` | 403 | No | Public API access must be explicitly enabled for the workspace; a missing access row is treated as disabled. | | `workspace_public_api_suspended` | 403 | No | Contact support — billing or compliance hold. | | `forbidden` | 403 | No | The key does not have permission for that resource. Check scope. | | `rate_limited` | 429 | Yes | Respect `Retry-After` then retry. See Rate Limits. | | `insufficient_credits` | 402 | No | Top up or wait for the monthly refill. Don't retry blindly. | | `internal_error` | 500 | Yes | Retry with backoff. Include `requestId` when reporting. | ## Worked example: `insufficient_credits` ```json title="Response body (402)" { "error": { "code": "insufficient_credits", "message": "Not enough credits to complete this request.", "requestId": "req_01HZ…" } } ``` On a 402, do not retry blindly. Call `GET /v1/usage` to read the current balance and the monthly refill date, then either top up or surface the gap to the caller. Agents that loop over many pages should check `X-Credits-Remaining` on successful metered calls and stop before the next request would fail. --- # Getting Started Source: https://docs.trendtrack.io/docs/guides/getting-started ## Quickstart Ask an admin to explicitly enable Public API access for the target workspace. Create a workspace-scoped API key in Trendtrack — see{" "} Authentication. Call an unmetered shell endpoint like `GET /v1/me` to confirm the credential resolves to the expected workspace. Call `GET /v1/usage` to inspect the current credit balance before running any metered call. If freshness matters, call `GET /v1/system/freshness` before analytics queries so you know the current latest-ready date. ## Base URLs Use an environment variable so scripts can switch base URLs without changing code: ```bash title="Shell" export TT_API_BASE_URL="https://api.trendtrack.io" ``` ## 30-second sanity check Run this in a terminal — it authenticates, resolves your workspace, and returns real JSON in under a second. No credits are spent. ```bash title="Shell" export TT_API_KEY="tt_live_…" export TT_API_BASE_URL="https://api.trendtrack.io" curl -s "$TT_API_BASE_URL/v1/workspace" \ -H "Authorization: Bearer $TT_API_KEY" \ -D - | head -20 ``` ```json title="Response (body)" { "data": { "id": "ws_01HZX0W3YJABCDEF", "name": "Acme Growth", "plan": "professional", "createdAt": "2025-09-12T10:22:31.000Z" }, "requestId": "req_01HZ…" } ``` Relevant response headers returned by the `curl -D -` flag: - `X-Request-Id` — quote this when reaching out to support. - `X-Credits-Remaining` — sent by metered endpoints and by unmetered `GET /v1/usage`, which reports the current balance. Shell endpoints (`/v1`, `/v1/health`, `/v1/me`, `/v1/workspace`, `/v1/usage`) are unmetered. They are the safest way to validate authentication, request IDs, and workspace resolution before moving on to metered business endpoints. `GET /v1/usage` still returns `X-Usage-Cost: 0`, `X-Credits-Used: 0`, and `X-Credits-Remaining`. A successful response always carries `{ data, requestId }` (plus `pagination` on collection endpoints). Errors follow the same shape — always parse `error.code`, not the human message: ```json title="Error envelope" { "error": { "code": "missing_api_key", "message": "Missing API key.", "requestId": "req_123" } } ``` ## Common first errors - **`401 missing_api_key` / `401 invalid_api_key`**: header missing or malformed. Double-check `Authorization: Bearer ` (no `x-api-key`, no quotes around the value). - **`401 credential_revoked` / `401 credential_expired`**: the key was deleted or rotated — issue a new one in workspace settings. - **`403 workspace_public_api_disabled`**: Public API access has not been explicitly enabled for the workspace yet. A missing access row is treated as disabled. - **`402 insufficient_credits`**: call `GET /v1/usage` to inspect the remaining balance, then top up or wait for the monthly refill. - **`429 rate_limited`**: respect the `Retry-After` header before retrying. See Rate Limits. Full list and status-code guidance lives in Errors. ## Pagination pattern Collection endpoints accept `limit` and `offset` (or a `page` parameter — check the operation page). Cost is charged per returned row, not per request, so always page conservatively: ```bash title="Paginated example" curl -X GET "$TT_API_BASE_URL/v1/ads?search=skincare&limit=50&offset=0" \ -H "Authorization: Bearer $TT_API_KEY" ``` `GET /v1/ads` always requires `search`. If you need advanced filters with no text term, use `POST /v1/ads/query` with a JSON body instead. - Start with a small `limit` (10–50) while integrating to avoid burning credits on a loop bug. - Watch the `X-Credits-Remaining` response header after every metered call. - Stop paginating when the server returns fewer rows than `limit`. ## Track usage as you go Metered responses can include: - `X-Usage-Cost` — credits consumed by that request - `X-Credits-Used` — credits consumed by that request - `X-Credits-Remaining` — balance after the call - `X-Credits-Source` — `recurring`, `topup`, or `hybrid` when a bucket is consumed - `X-Request-Id` — include it when contacting support `GET /v1/usage` is unmetered, but it still returns `X-Usage-Cost: 0`, `X-Credits-Used: 0`, and `X-Credits-Remaining`. See Credits & Billing for the complete consumption model. ## Agent integration path For tracked-brand questions, resolve the workspace brandtracker first instead of searching the public ad library: 1. `GET /v1/me` — validate the key and workspace. 2. `GET /v1/usage` — check credit budget before metered loops. 3. `GET /v1/system/freshness` (optional) — read `latestReadyDate` and `dataFreshnessLagDays` before reporting historical, freshness-sensitive metrics. 4. `GET /v1/brandtrackers?page=1&limit=100` — match the user's brand name against `data[].name` and carry `data[].id` as `brandtrackerId`. 5. `GET /v1/brandtrackers/{brandtrackerId}/overview` — start with the overview for a broad read, then use canonical top-ads ranking calls when the user asks for winners or movers. 6. `GET /v1/brandtrackers/{brandtrackerId}/top-ads?sortBy=currentRank` — current ranking. Use `sortBy=rankDelta7d`, `rankDelta14d`, or `rankDelta30d` for rank movers, and `sortBy=reach`, `reachDelta1d`, `reachDelta7d`, or `reachDelta30d` for reach rankings. Do not add `period` or `snapshotDate` to canonical top-ads ranking calls; they are deprecated compatibility parameters on `/top-ads`. `/scaling-ads` and `/ad-rank` are legacy compatibility endpoints for rank movers and may return an empty `trajectory` on the ES-backed path. ## Key concepts A few field names worth knowing before browsing the reference: - **`rank` / `currentRank`** — the current Facebook page rank returned on top-ads responses. Sort canonical ranking calls with `sortBy=currentRank`. - **`rankDelta7d` / `rankDelta14d` / `rankDelta30d`** — canonical top-ads sort keys for rank movers. Use these instead of starting new integrations on `/scaling-ads` or `/ad-rank`. - **`reach`** — the Meta Ad Library term for the public-facing impressions-style metric, exposed directly by our API. On brandtracker/top-ads GET endpoints, sort with `sortBy=reach`, `reachDelta1d`, `reachDelta7d`, or `reachDelta30d`; `impressions` is accepted as a reach alias. On `POST /v1/ads/query`, use `sortBy: "reach"` with `order`. - **`daysRunning`** — number of calendar days an ad has been observed live. Useful as a longevity signal (winners typically stay live > 14 days). - **`firstSeenAt`** — first timestamp at which Trendtrack observed the ad. Combined with `daysRunning`, it lets you reconstruct the live window. - **`snapshotDate`** — an anchor date for historical/freshness-aware endpoints. It is deprecated and ignored on canonical `/top-ads` ranking calls. See Time windows for where `period` and `snapshotDate` still apply. ## Next steps Header format, key rotation, and what Trendtrack validates on every request. Metered behavior, monthly refill, carry-over, and response headers. Throttling behavior and `Retry-After` handling. The stable error envelope and the full public error-code list. Common failures, causes, and the fastest path to a working request. Resource-by-resource operation reference with request and response samples. --- # Search by image Source: https://docs.trendtrack.io/docs/guides/image-search Two endpoints use the same visual search as the Trendtrack app: - `POST /v1/products/image-search` returns the store products that look like an image, most similar first. - `POST /v1/shops/image-search` returns the shops selling them, the most active advertisers (Meta active ads) first, each with its closest products. ## Send the image Send exactly one of: | Field | How | | ---------- | ------------------------------------------------------------------------------------------- | | `image` | A file in `multipart/form-data`: JPEG, PNG or WEBP, 10 MB max. Larger files return `413`. | | `imageUrl` | A public `http(s)` URL in a JSON body. The server downloads it (10 MB max). | | `searchId` | The `meta.searchId` of a previous answer, to read its next pages without sending the image. | ```bash title="Shops selling this product, from a file" export TT_API_BASE_URL="https://api.trendtrack.io" curl -s -X POST "$TT_API_BASE_URL/v1/shops/image-search" \ -H "Authorization: Bearer $TT_API_KEY" \ -F "image=@product.jpg" \ -F "limit=10" ``` ```bash title="Products that look like an image URL" curl -s -X POST "$TT_API_BASE_URL/v1/products/image-search" \ -H "Authorization: Bearer $TT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"imageUrl": "https://cdn.shopify.com/s/files/1/0000/products/lamp.jpg", "limit": 10}' ``` ## Read the next pages Every first answer carries `meta.searchId`. Send it back with a higher `offset` and the same options: the image is not sent or computed again, and the results stay in the same order. ```bash title="Page 2" curl -s -X POST "$TT_API_BASE_URL/v1/shops/image-search" \ -H "Authorization: Bearer $TT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"searchId": "c97f4092-88a0-4f28-8fb7-57dac06ad1d8", "offset": 10, "limit": 10}' ``` A `searchId` belongs to the workspace of the key that created it; another workspace gets `404`. ## One shop, one row A brand often sells the same product on several storefronts, and a shop often lists one product several times (variants, duplicate photos). The results count each of them once, so you never pay twice for the same shop: - A product repeated in one shop is returned once. - One Shopify store served on several domains is one shop. - With `groupBrands` (default `true`), the storefronts of one brand (same name across countries and subdomains, such as `fridoorthotics.com` and `fridoorthotics.co.uk`) are one shop. The shop search returns its most active storefront as `shop` and the others in `otherStorefronts`. Set `groupBrands: false` to list every storefront. - The product search returns one product per shop by default. Set `maxPerShop` (up to 10, `0` for no cap) to get more. - The shop search returns, per shop, `matchingProducts` (distinct products that match) and its closest `products` (`productsPerShop`, 3 by default, up to 10). Each product price is in the currency of the storefront that sells it. ## Similarity and credits `similarityScore` is the visual similarity between your image and the product photo, from `0.7` to `1`. Results below `0.7` are not returned. Both endpoints cost 4 credits per row returned: a product for `/v1/products/image-search`, a shop for `/v1/shops/image-search`. Other storefronts and sample products of a shop are included in its row. A request that fails (unreadable image, `503` while the image search is unavailable) costs nothing. ## From Claude or ChatGPT The MCP tools `search_products_by_image` and `search_shops_by_image` take `image_url` (or `search_id` for the next pages), plus `max_per_shop`, `group_brands` and `products_per_shop`. An image pasted in the conversation cannot be passed to a tool: give the assistant a link to the image. --- # Rate Limits Source: https://docs.trendtrack.io/docs/guides/rate-limits ## Current behavior Trendtrack owns authenticated public API rate limiting in the backend runtime. If a request is blocked, the API returns a canonical `429 rate_limited` response. ## Headers to watch - `Retry-After` tells you when to retry after a `429`. - `X-Request-Id` helps correlate support or debugging investigations. ## Implementation guidance - Back off and retry after the interval in `Retry-After`. - Treat rate limiting separately from billing failures such as `insufficient_credits`. - Use the raw OpenAPI and Swagger references to verify per-endpoint behavior as the surface evolves. --- # Time windows Source: https://docs.trendtrack.io/docs/guides/time-windows Use two separate mental models: - **Current rankings** use `/top-ads?sortBy=...`. They are not snapshot-window queries. - **Historical analytics** use endpoint-specific `period`, `timePeriod`, `timeWindow`, and optional `snapshotDate` controls where documented. ## Current ranking endpoints | Goal | Endpoint | Sort recipe | | ------------------------- | ------------------------------------------------ | ------------------------------------------------------------------ | | Brandtracker current rank | `GET /v1/brandtrackers/{brandtrackerId}/top-ads` | `sortBy=currentRank` | | Workspace current rank | `GET /v1/workspace/top-ads` | `sortBy=currentRank` | | Reach ranking | `/top-ads` | `sortBy=reach`, `reachDelta1d`, `reachDelta7d`, or `reachDelta30d` | | Rank movers | `/top-ads` | `sortBy=rankDelta7d`, `rankDelta14d`, or `rankDelta30d` | `period` and `snapshotDate` are deprecated compatibility parameters on these canonical top-ads ranking paths and are ignored. The response rank fields may appear as `rank` / `currentRank` depending on the object you are reading. ```bash title="Current rank example" export TT_API_BASE_URL="https://api.trendtrack.io" curl -s "$TT_API_BASE_URL/v1/brandtrackers/$BT/top-ads?sortBy=currentRank&limit=50" \ -H "Authorization: Bearer $TT_API_KEY" ``` ```bash title="Rank movers example" curl -s "$TT_API_BASE_URL/v1/brandtrackers/$BT/top-ads?sortBy=rankDelta7d&limit=50" \ -H "Authorization: Bearer $TT_API_KEY" ``` ## Compatibility ranking endpoints `GET /v1/brandtrackers/{brandtrackerId}/ad-rank`, `GET /v1/brandtrackers/{brandtrackerId}/scaling-ads`, and `GET /v1/workspace/scaling-ads` remain available for existing clients. For new integrations, prefer `/top-ads?sortBy=rankDelta7d|rankDelta14d|rankDelta30d`. Compatibility notes: - `timeWindow=last7d|last14d|last30d` maps to the corresponding rank-delta ranking. - `snapshotDate` is deprecated and ignored on the ES-backed compatibility path. - `trajectory` may be an empty array on the ES-backed path. ## Historical and freshness-aware endpoints Other analytics endpoints can still use rolling windows and snapshot anchors. Check each operation page for the exact parameter name. | Endpoint family | Parameter | Recommended default | Notes | | ------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | Brandtracker hooks, landing pages, creatives, media mix, demography | `timePeriod` | Operation default, often `last7d`/`last30d` | Historical/freshness semantics still apply where documented. | | Brandtracker overview | `topAdsPeriod`, `landingPagesTimePeriod` | Operation default | Overview keeps its documented aggregate controls. Use `/top-ads?sortBy=...` for dedicated ranking drilldowns. | | Workspace aggregate analytics | `period` | Operation default | Applies to historical aggregate endpoints such as hooks, landing pages, ad copies, and media mix. | ## `snapshotDate` — historical anchor date Where supported, `snapshotDate` fixes the "as-of" moment used to interpret statuses and resolve historical counts. It accepts a `YYYY-MM-DD` date or the literal string `latest`. - **Omitted** (or `latest`) — historical analytics endpoints resolve to the latest **ready** snapshot date, not the latest scheduled/indexing date. - **Specific date** — the response is reconstructed as it would have been on that date. `status: "active"` is interpreted relative to that snapshot. ## Snapshot readiness and freshness checks Use these endpoints when you need explicit freshness guarantees: - `GET /v1/brandtrackers/{brandtrackerId}/snapshots` returns: - `latestReadyDate` - `latestScheduledDate` - per-date readiness status (for example ready vs indexing) - `GET /v1/system/freshness` returns global readiness (`latestReadyDate`, `latestScheduledDate`, `dataFreshnessLagDays`). ## Common pitfalls - **Adding `period` to top-ads ranking calls.** It is accepted for compatibility but ignored. Choose the ranking with `sortBy` instead. - **Using `/scaling-ads` for new rank-mover integrations.** Prefer `/top-ads?sortBy=rankDelta7d`, `rankDelta14d`, or `rankDelta30d`; compatibility endpoints may return empty `trajectory`. - **Treating `latestScheduledDate` as query-ready.** Scheduled/indexing can be ahead of ready data; use `latestReadyDate` for stable historical reporting. ## Recommended defaults for agents When building an agent that surveys a brandtracker once per session: 1. Resolve the brand with `GET /v1/brandtrackers?page=1&limit=100` and carry the matching `data[].id` as `brandtrackerId`. 2. Start with `GET /v1/brandtrackers/{brandtrackerId}/overview` for a broad read. 3. Use `GET /v1/brandtrackers/{brandtrackerId}/top-ads?sortBy=currentRank` for current winners. 4. Use `sortBy=rankDelta7d`, `rankDelta14d`, or `rankDelta30d` for rank movers. 5. Optionally check `GET /v1/system/freshness` when historical freshness is critical. --- # Troubleshooting Source: https://docs.trendtrack.io/docs/guides/troubleshooting Every API error returns the same envelope. Always parse `error.code`, not the human message: ```json title="Stable error envelope" { "error": { "code": "missing_api_key", "message": "Missing API key.", "requestId": "req_123" } } ``` If you need to contact support, include the `X-Request-Id` response header (or the `requestId` field) — it lets us correlate your call with backend logs instantly. ## 401 — Authentication failed ### `missing_api_key` The `Authorization` header is missing or empty. - Check that you are sending `Authorization: Bearer ` (not `x-api-key`, not `Api-Key`). - Verify your HTTP client isn't stripping custom headers. Some CLIs need `--header` escaping. ### `invalid_api_key` The header was present but Trendtrack could not resolve it to a key. - Copy the key again from the workspace API settings — whitespace at either end breaks matching. - Confirm your base URL is `https://api.trendtrack.io` unless your TrendTrack contact gives you a different origin; avoid preview URLs. ### `credential_not_found` / `credential_revoked` / `credential_expired` The key resolved but is no longer usable. - Rotate the key in Trendtrack → Workspace settings → API. - If this happened unexpectedly, check whether another teammate revoked the key. ## 402 — `insufficient_credits` The request was authenticated but the workspace does not have enough credits for the requested work. - Call `GET /v1/usage` to see the remaining balance. It is unmetered but still returns `X-Usage-Cost: 0`, `X-Credits-Used: 0`, and `X-Credits-Remaining`; metered calls may report `X-Credits-Source` as `recurring`, `topup`, or `hybrid`. - Top up from the webapp billing page. The fixed rate is `$1 = 1,000 credits`, minimum top-up `$10`. - Remember: cost is charged per returned row, not per request. Paginating with a smaller `limit` reduces each call's cost. ## 403 — Workspace or permission denied ### `workspace_public_api_disabled` / `workspace_public_api_suspended` The workspace itself cannot call the API right now. - Ask an admin to explicitly enable Public API access in workspace settings. If no `workspace_public_api_access` row exists, TrendTrack treats the workspace as disabled. - Contact support if the workspace was suspended. ### `forbidden` The credential is valid but not allowed to reach this resource or action. - Confirm the endpoint is exposed on the Public API (not every webapp endpoint is). - Check workspace-level role requirements — some resources are admin-only. ## 404 — Not found The path exists in the docs but the server does not have that record. - Verify IDs (`adId`, `shopId`, etc.) — a trailing newline or wrong casing often masquerades as 404. - For collection endpoints, 404 typically means the resource is not in your workspace's scope. ## 429 — `rate_limited` You hit the public rate limit. - Respect the `Retry-After` header before retrying. - Back off exponentially if retries keep getting throttled. - See Rate Limits for the full model. ## 500 — `internal_error` Server-side failure. This one is on us. - Include the `requestId` in any support message. - If a retry with the exact same payload succeeds, the error was transient. If it keeps failing, reach out. ## Request shape surprises - **`GET /v1/ads` fails or returns a validation error** — add the required `search` parameter, for example `/v1/ads?search=skincare&limit=25`. For advanced filters with no text term, use `POST /v1/ads/query`. - **Advanced `/query` endpoint ignores your filters** — send `Content-Type: application/json` and put filters in the JSON request body. Query-string filters are for the lightweight GET endpoints only. - **Empty collection returned but you expected results** — check that filters (`status`, `platform`, `mediaType`) are not narrower than intended. Start with the minimal query, then add filters one by one. - **Fewer rows than `limit`** — that's the end of the collection for the current query. Stop paginating. - **Response missing a field you saw before** — schema changes are additive. If a field disappears you think is stable, it likely was renamed or moved into a nested object. Check the API Reference for the current shape. ## Still stuck? - Keep Errors open for the full code list. - Capture the `X-Request-Id` and share it with support along with the exact URL and a sanitized copy of the request body. --- # Introduction Source: https://docs.trendtrack.io/docs Get your API key Quickstart ## Built for AI agents Use the primary Markdown playbook when an agent needs to choose endpoints and avoid expensive discovery mistakes: ``` https://docs.trendtrack.io/docs/agent-guide.md ``` The guide links to focused Markdown pages for lookup, shops, brandtrackers, ads, workspace, usage/credits, and time windows. It starts with the most important rule: when a user provides a brand, domain, handle, or page id, call `/v1/lookup` first. For a full generated dump, use: ``` https://docs.trendtrack.io/docs/llms-full.txt ``` Drop either URL into Cursor, Claude, ChatGPT, Windsurf, Copilot, or any agent with web access, paste your [API key](https://app.trendtrack.io/workspace/settings/api) alongside it so the agent can authenticate requests, then prompt with natural queries like _"Find Shopify stores selling skincare in France with active Meta ads"_. The agent plans the call, you review the result. ## Guides Enable access, create a key, and make your first authenticated request. Learn how to authenticate your API requests using API keys. Understand credits, top-ups, usage headers, and metered behavior. Learn about rate limits, quotas, and how to handle them. Read about the different error codes and types returned by the API. Browse the generated endpoint reference grouped by resource. --- # Use Trendtrack with ChatGPT Source: https://docs.trendtrack.io/docs/integrations/chatgpt ChatGPT can connect to Trendtrack through a custom MCP app using Trendtrack's remote MCP endpoint. ```text title="MCP endpoint" https://api.trendtrack.io/v1/mcp ``` ## Setup Make sure Public API access is enabled for your workspace before connecting ChatGPT. If needed, follow Authentication first. In ChatGPT, click your profile in the bottom-left corner, then click Settings. ![ChatGPT profile menu showing Settings](/integrations/chatgpt/screenshots/01-profile-settings.png) Go to Apps, then open Advanced settings. Enable Developer mode, then click Create an app. ![ChatGPT Apps advanced settings with Developer mode and Create an app](/integrations/chatgpt/screenshots/02-developer-mode-create-app.png) Set the app name to Trendtrack, set/paste the MCP server URL to https://api.trendtrack.io/v1/mcp, then click Create. On Trendtrack, click Allow access to complete OAuth. ![Trendtrack Allow access OAuth screen](/integrations/chatgpt/screenshots/03-trendtrack-allow-access-oauth.png) Trendtrack is then available inside ChatGPT. ## Example prompts - Find Shopify stores selling skincare in France with active Meta ads and summarize any TikTok presence fields. - Search TikTok library creatives for collagen gummies; include ads and organic videos. - Look up this brand and summarize its current top Meta ads. - Show my workspace's fastest scaling ads this week. - Check remaining usage credits before running a large query. To find who sells a product from its picture, give ChatGPT a link to the image: `search_products_by_image` returns the lookalike products and `search_shops_by_image` the shops selling them, most active advertisers first. An image pasted in the conversation cannot be passed to the tools. For TikTok creative discovery, ask ChatGPT to use `search_tiktok_library`. For shop questions, `search_shops` can include additive TikTok presence/count fields, but linked advertisers and `/v1/ads*` remain Meta/Facebook-only. If you are mirroring the same workflow over REST, use the dedicated TikTok endpoints: ```text title="TikTok REST request examples" GET /v1/tiktok/library?search=collagen%20gummies&type=all&limit=10 POST /v1/tiktok/library/query {"search":["collagen gummies"],"type":"ad","status":"active","limit":10} GET /v1/tiktok/library/tiktok_7078586231734521093 GET /v1/shops/3f8aa146-6f96-46e8-9781-64db5166f9a8/tiktok/library?limit=10 ``` ## Brandtracker write examples Once you approve the `trendtrack:brandtrackers.write` OAuth scope, ChatGPT can manage tracked brands through MCP write tools. API-key MCP callers are workspace-authorized like REST API keys and do not use OAuth scopes. ```text title="Add a tracked brand by domain" Use Trendtrack add_to_brandtracker with domain "examplebrand.com" and folder_id 42. ``` ```text title="Create and organize a folder" Use Trendtrack create_brandtracker_folder named "Q3 competitors", then move_tracked_brands with brandtracker_ids ["..."] and folder_id from the created folder. ``` ```text title="Delete safely" Use Trendtrack delete_brandtracker_folder with folder_id 42, action "move_to_default", confirm true. Only use action "delete_tracked_brands" when I explicitly want the tracked brands deactivated. ``` ## Favorites write examples The default OAuth grant includes `trendtrack:favorites.read` so ChatGPT can use `list_favorites`, and `trendtrack:favorites.write` for favorites MCP write/share tools. Write tools include `create_favorite_folder`, `update_favorite_folder`, `set_favorite_folder_visibility`, `delete_favorite_folder`, `reorder_favorite_folders`, `add_favorite_item`, `move_favorite_item`, `remove_favorite_item`, `create_ad_share_link`, and `create_favorite_folder_share_link`. Use `type: "ads" | "shops" | "emails"`; `shops` means website/shop favorites. `scope` defaults to `workspace`, while `personal` requires delegated-user authorization. Destructive tools such as `delete_favorite_folder` and `remove_favorite_item` require `confirm: true`. ```text title="Save and organize a shop favorite" Use Trendtrack create_favorite_folder with type "shops", name "Competitor shops", then add_favorite_item with type "shops", item_id "...", and folder_id from the created folder. ``` ```text title="Delete safely" Use Trendtrack delete_favorite_folder with type "ads", folder_id "...", mode "move_items_to_root", confirm true. ``` ```text title="Create a share link" Use Trendtrack create_favorite_folder_share_link with type "ads" and folder_id "...". Shops and emails are not shareable through MCP in this version. ``` Favorite capabilities: ads support hierarchy, reorder, visibility, and share links; shops support flat folders and visibility but not hierarchy/reorder; emails support hierarchy, reorder, and visibility. Saved favorite IDs come from `list_favorites`: ads are numeric, shops/emails are UUIDs. For public ad scaling prompts like “top ads leggings femme sur les 7 derniers jours”, ask ChatGPT to use the generated `POST /v1/ads/query` 7-day scaling example (`reachDelta7d`, `last7d`, `minReach: 1`) rather than first-seen date filters. ## Cost and safety notes - Start with read-only discovery endpoints like `/v1/me`, `/v1/workspace`, `/v1/usage`, and `/v1/lookup`. - Read/list metered endpoints consume credits per returned row: 4 per shop or product, 3 per advertiser, 2 per email, 1.5 per Meta ad, 1 for the rest. Write and share calls are fixed-cost. - Brandtracker create/reactivate and destructive delete operations also check brandtracker mutation quota and active tracker slots before committing changes. - `trendtrack:favorites.read` is part of the default OAuth grant for `list_favorites`; `trendtrack:favorites.write` is opt-in and required only for favorites write/share tools. API-key MCP callers rely on REST-style workspace authorization. - Destructive MCP tools require `confirm: true`; bulk and folder destructive operations count as one persistent create/delete quota operation while reporting affected counts. - See Credits & Billing and Rate Limits before running large queries. ## Troubleshooting - **ChatGPT can't create the app:** confirm Developer mode is enabled in Apps advanced settings. - **The app can't connect:** confirm the MCP URL is the canonical extension-server `/v1/mcp` endpoint: `https://api.trendtrack.io/v1/mcp`. - **ChatGPT can't access workspace data:** reconnect the app and complete OAuth again. - **Unexpected credit usage:** ask ChatGPT to check usage first and run smaller limits. - **429 rate limits:** wait and retry according to Rate Limits. ## Next steps Start with your first authenticated Trendtrack calls. Validate API access and credential setup. Understand credit usage and metered endpoints. Handle throttling safely. Explore all available endpoints. --- # Use Trendtrack with Claude Source: https://docs.trendtrack.io/docs/integrations/claude Claude can connect to Trendtrack through a custom connector using Trendtrack's remote MCP endpoint. ```text title="MCP endpoint" https://api.trendtrack.io/v1/mcp ``` ## Setup Make sure Public API access is enabled for your workspace before connecting Claude. If needed, follow Authentication first. In Claude, open Settings and go to Connectors. ![Claude Manage connectors menu](/integrations/claude/screenshots/01-manage-connectors-menu.png) Click Add custom connector, set the name to Trendtrack, set/paste the Remote MCP server URL to https://api.trendtrack.io/v1/mcp, then click Connect. ![Add custom connector in connectors settings](/integrations/claude/screenshots/02-add-custom-connector-settings.png) On Trendtrack, click Allow access to complete OAuth. ![Trendtrack Allow access OAuth screen](/integrations/claude/screenshots/03-trendtrack-allow-access-oauth.png) Test the connection with a quick prompt such as: Use Trendtrack to check my workspace and summarize which API tools are available. Trendtrack is then available in Claude and Claude Desktop. ## Example prompts - Find Shopify stores selling skincare in France with active Meta ads and summarize any TikTok presence fields. - Search TikTok library creatives for collagen gummies; include ads and organic videos. - Look up this brand and summarize its current top Meta ads. - Show my workspace's fastest scaling ads this week. - Check remaining usage credits before running a large query. To find who sells a product from its picture, give Claude a link to the image: `search_products_by_image` returns the lookalike products and `search_shops_by_image` the shops selling them, most active advertisers first. An image pasted in the conversation cannot be passed to the tools. For TikTok creative discovery, ask Claude to use `search_tiktok_library`. For shop questions, `search_shops` can include additive TikTok presence/count fields, but linked advertisers and `/v1/ads*` remain Meta/Facebook-only. If you are mirroring the same workflow over REST, use the dedicated TikTok endpoints: ```text title="TikTok REST request examples" GET /v1/tiktok/library?search=collagen%20gummies&type=all&limit=10 POST /v1/tiktok/library/query {"search":["collagen gummies"],"type":"ad","status":"active","limit":10} GET /v1/tiktok/library/tiktok_7078586231734521093 GET /v1/shops/3f8aa146-6f96-46e8-9781-64db5166f9a8/tiktok/library?limit=10 ``` ## Brandtracker write examples Once you approve the `trendtrack:brandtrackers.write` OAuth scope, Claude can manage tracked brands through MCP write tools. API-key MCP callers are workspace-authorized like REST API keys and do not use OAuth scopes. ```text title="Add a tracked brand by domain" Use Trendtrack add_to_brandtracker with domain "examplebrand.com" and folder_id 42. ``` ```text title="Create and organize a folder" Use Trendtrack create_brandtracker_folder named "Q3 competitors", then move_tracked_brands with brandtracker_ids ["..."] and folder_id from the created folder. ``` ```text title="Delete safely" Use Trendtrack delete_brandtracker_folder with folder_id 42, action "move_to_default", confirm true. Only use action "delete_tracked_brands" when I explicitly want the tracked brands deactivated. ``` ## Favorites write examples The default OAuth grant includes `trendtrack:favorites.read` so Claude can use `list_favorites`, and `trendtrack:favorites.write` for favorites MCP write/share tools. Write tools include `create_favorite_folder`, `update_favorite_folder`, `set_favorite_folder_visibility`, `delete_favorite_folder`, `reorder_favorite_folders`, `add_favorite_item`, `move_favorite_item`, `remove_favorite_item`, `create_ad_share_link`, and `create_favorite_folder_share_link`. Use `type: "ads" | "shops" | "emails"`; `shops` means website/shop favorites. `scope` defaults to `workspace`, while `personal` requires delegated-user authorization. Destructive tools such as `delete_favorite_folder` and `remove_favorite_item` require `confirm: true`. ```text title="Save and organize a shop favorite" Use Trendtrack create_favorite_folder with type "shops", name "Competitor shops", then add_favorite_item with type "shops", item_id "...", and folder_id from the created folder. ``` ```text title="Delete safely" Use Trendtrack delete_favorite_folder with type "ads", folder_id "...", mode "move_items_to_root", confirm true. ``` ```text title="Create a share link" Use Trendtrack create_favorite_folder_share_link with type "ads" and folder_id "...". Shops and emails are not shareable through MCP in this version. ``` Favorite capabilities: ads support hierarchy, reorder, visibility, and share links; shops support flat folders and visibility but not hierarchy/reorder; emails support hierarchy, reorder, and visibility. Saved favorite IDs come from `list_favorites`: ads are numeric, shops/emails are UUIDs. For public ad scaling prompts like “top ads leggings femme sur les 7 derniers jours”, ask Claude to use the generated `POST /v1/ads/query` 7-day scaling example (`reachDelta7d`, `last7d`, `minReach: 1`) rather than first-seen date filters. ## Cost and safety notes - Start with read-only discovery endpoints like `/v1/me`, `/v1/workspace`, `/v1/usage`, and `/v1/lookup`. - Read/list metered endpoints consume credits per returned row: 4 per shop or product, 3 per advertiser, 2 per email, 1.5 per Meta ad, 1 for the rest. Write and share calls are fixed-cost. - Brandtracker create/reactivate and destructive delete operations also check brandtracker mutation quota and active tracker slots before committing changes. - `trendtrack:favorites.read` is part of the default OAuth grant for `list_favorites`; `trendtrack:favorites.write` is opt-in and required only for favorites write/share tools. API-key MCP callers rely on REST-style workspace authorization. - Destructive MCP tools require `confirm: true`; bulk and folder destructive operations count as one persistent create/delete quota operation while reporting affected counts. - See Credits & Billing and Rate Limits before running large queries. ## Troubleshooting - **Connector can't connect:** confirm the MCP URL is the canonical extension-server `/v1/mcp` endpoint: `https://api.trendtrack.io/v1/mcp`. - **Claude can't access workspace data:** reconnect the connector and complete OAuth again. - **Unexpected credit usage:** ask Claude to check usage first and run smaller limits. - **429 rate limits:** wait and retry according to Rate Limits. ## Next steps Start with your first authenticated Trendtrack calls. Validate API access and credential setup. Understand credit usage and metered endpoints. Handle throttling safely. Explore all available endpoints. --- # Use Trendtrack with n8n Source: https://docs.trendtrack.io/docs/integrations/n8n n8n's HTTP Request node is enough to drive the entire Trendtrack public API. There is no custom node — you authenticate with a Bearer header, hit `https://api.trendtrack.io/v1/...`, and pipe the JSON into Slack, Discord, Notion, Sheets, Airtable, HubSpot, or any other n8n destination. This guide gives you: - A working setup: API key, n8n credential, first authenticated call, credit-budget visibility. - An endpoint cookbook: one mini-recipe per resource family, with the exact HTTP node configuration. - A gallery of ten importable workflows covering daily creative monitoring, scaling alerts, shop discovery, email watch, and on-demand brand 360 reports. ## Setup Enable Public API access on the workspace and create a workspace-scoped API key. The button lives in workspace settings — see Authentication for the full key-issuance and rotation policy. Add an **HTTP Request** node to your n8n canvas. From the node search, type "HTTP" and pick **HTTP Request**. For one-off HTTP Request nodes, create a **Header Auth** credential in n8n: name it `Trendtrack public API`, set the header to `Authorization` and the value to `Bearer YOUR_API_KEY`. The downloadable workflows below instead use `TRENDTRACK_API_KEY` as an environment variable so they can be imported without bundled credentials. Verify the credential with a zero-credit call to `GET /v1/me`. If the response contains your workspace, you're wired up. Inspect the response **Headers** tab to confirm `X-Request-Id` is returned. Metered endpoints additionally surface `X-Credits-Used`, `X-Credits-Remaining`, and `X-Credits-Source`. Use these values to monitor budget and to quote a request ID when you contact support. Optional but recommended: store the key as the n8n environment variable `TRENDTRACK_API_KEY` and reference it with `={{ $env.TRENDTRACK_API_KEY }}` in the credential. The downloadable workflows below all assume this variable exists. ### What a healthy first call looks like ```bash title="Shell — same call without n8n" curl -s "https://api.trendtrack.io/v1/me" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ```json title="Response (body)" { "data": { "credential": { "id": "cred_01HZ…", "name": "n8n production", "accessLevel": "workspace", "createdAt": "2026-04-12T10:22:31.000Z" }, "workspace": { "id": "ws_01HZX0W3YJABCDEF", "slug": "acme-growth", "name": "Acme Growth" } }, "requestId": "req_01HZ…" } ``` Shell endpoints (`/v1/me`, `/v1/workspace`, `/v1/usage`, `/v1/health`) are unmetered — they're the safest way to validate authentication and resolve workspace context before running metered loops. See Getting Started for the full bootstrap sequence and Errors for the error envelope you'll match against in n8n's IF nodes. ## Endpoint cookbook Every recipe below is a single HTTP Request node. They are intentionally minimal — combine them with n8n's `Set`, `Function`, `Split In Batches`, and `IF` nodes to build the complete workflows in the gallery. ### 1. Discovery — `POST /v1/ads/query` Advanced ad search. Use it for niche-keyword scouting, reach thresholds, and date-bounded queries. - **Method**: POST - **URL**: `https://api.trendtrack.io/v1/ads/query` - **Body Content Type**: JSON - **Pagination**: `page` + `limit` (max 100); 1.5 credits per returned ad, rounded per request. ```json title="HTTP Request body" { "search": ["serum"], "searchType": "adCopy", "sortBy": "reach", "order": "desc", "status": "active", "minReach": 50000, "reachPeriod": "last7d", "adsTimePeriod": "last30d", "limit": 25, "page": 1 } ``` The response carries `{ data, pagination, requestId }`. `pagination.totalPages` tells you when to stop a `Split In Batches` loop. ### 2. Brand resolution — `GET /v1/lookup` Zero-credit identifier resolution. Always call this first when you have a user-supplied brand name, domain, Instagram handle, or Facebook page id and need a stable Trendtrack identifier. - **Method**: GET - **URL**: `https://api.trendtrack.io/v1/lookup` - **Query parameters**: `q` (required, 2–200 chars), `type` (`auto` | `brandtracker` | `advertiser` | `shop`), `limit` (1–10). ```bash title="cURL equivalent" curl -s "https://api.trendtrack.io/v1/lookup?q=allbirds.com&type=auto" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` The response gives you `brandtracker.id`, `advertiser.id`, and `shop.id` for the matched brand. Carry those identifiers downstream. ### 3. Brandtracker folders — `GET /v1/workspace/folders` Folders group the brandtrackers you track. Several aggregate endpoints accept `folderIds` to scope a query to a folder (e.g. "skincare clients" vs "supplements clients"). Resolve folder ids once, cache them in n8n, then pass them as repeated query params or a comma-separated list. - **Method**: GET - **URL**: `https://api.trendtrack.io/v1/workspace/folders` - **Cost**: unmetered. `folderIds` is currently honored on `/v1/workspace/hooks`, `/v1/workspace/ad-copies`, `/v1/workspace/landing-pages`, `/v1/workspace/media-mix`, and `/v1/brandtrackers`. It is **not** accepted on the canonical `/v1/workspace/top-ads` ranking endpoint today — for folder-scoped rankings or rank movers, the recommended pattern is to call `/v1/workspace/top-ads` and filter the response client-side on `brandtracker.folderId`. (`/v1/workspace/scaling-ads` is a legacy compatibility endpoint that still accepts `folderIds`; new integrations should prefer `/v1/workspace/top-ads?sortBy=rankDelta7d` + client-side filtering.) ### 4. Workspace top creatives — `GET /v1/workspace/top-ads` Canonical current-ranking endpoint across every active brandtracker in the workspace, in a single metered call. Use it as the spine of any "what's working right now" dashboard. - **Method**: GET - **URL**: `https://api.trendtrack.io/v1/workspace/top-ads` - **Query parameters**: `page`, `limit` (max 100), `sortBy`, `euOnly`, `includeInactive`. - **`sortBy` values**: - `currentRank` — current Facebook page rank. - `reach`, `reachDelta1d`, `reachDelta7d`, `reachDelta30d` — reach rankings (`impressions` is an accepted alias for `reach`). - `rankDelta7d`, `rankDelta14d`, `rankDelta30d` — rank movers (use these for scaling alerts). ```bash title="Daily top reach mover" curl -s "https://api.trendtrack.io/v1/workspace/top-ads?sortBy=reachDelta1d&limit=10" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` `period` and `snapshotDate` are deprecated on this endpoint and ignored — drive everything from `sortBy`. See Time windows for the full picture. ### 5. Hooks, ad copies, landing pages — `/v1/workspace/{hooks,ad-copies,landing-pages}` Aggregated creative analytics across the workspace. Same query-param shape on all three. - **Query parameters**: `page`, `limit`, `folderIds` (optional, comma-separated or repeated), and endpoint-specific time controls. - **Cost**: 1 credit per returned row. ```bash title="Top hooks for a folder" curl -s "https://api.trendtrack.io/v1/workspace/hooks?folderIds=fold_skincare,fold_supplements&limit=20" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ### 6. Shops discovery — `POST /v1/shops/query` Find Shopify-style shops by category, technology, market, traffic, and ad activity. This is the broader cousin of `/v1/ads/query` — instead of returning ads, it returns the shops that run them. - **Method**: POST - **URL**: `https://api.trendtrack.io/v1/shops/query` - **Pagination**: `offset` + `limit` (offset-based, not page-based). - **Cost**: 4 credits per returned shop. ```json title="Skincare shops in France with active Meta ads" { "search": "skincare", "searchType": "productName", "sortBy": "activeAds", "order": "desc", "adsTimePeriod": "last30d", "minActiveAds": 10, "mainMarketCountries": ["FR"], "technologies": ["shopify"], "limit": 25, "offset": 0 } ``` Resolve filter values (categories, technologies, pixels, Shopify apps) ahead of time via `/v1/facets/*` (see recipe 10). ### 7. Shop intelligence — `GET /v1/shops/{shopId}/...` Once you have a `shopId` (from `/v1/lookup` or `/v1/shops/query`), the per-shop endpoints unlock product, social, advertiser, and email history. - `GET /v1/shops/{shopId}/products?sortBy=popularity&limit=10` — best-sellers. - `GET /v1/shops/{shopId}/socials/history?period=day&days=90` — Facebook/Instagram follower time-series. - `GET /v1/shops/{shopId}/similar` — adjacent shops to expand prospecting. - `GET /v1/shops/{shopId}/advertisers` — Facebook pages running ads for this shop. - `GET /v1/shops/{shopId}/emails?sentAfter=2026-04-01` — recent email campaigns from this shop. Each endpoint is metered per returned row. ### 8. Email campaigns — `POST /v1/emails/query` Workspace-wide promotional email discovery. Useful for tracking competitor campaigns, sale calendars, and launch cadence. ```json title="Black-Friday-style campaigns from premium Shopify shops" { "search": ["sale", "black friday"], "searchType": "subject", "keywordMode": "any", "shopifyPlan": "plus", "minMonthlyVisits": 50000, "limit": 25, "page": 1 } ``` ### 9. Advertiser-level discovery — `POST /v1/advertisers/query` Rank Facebook pages directly — useful when you want a "most active in my vertical" leaderboard rather than ad-by-ad analytics. - **Sort options**: `relevance`, `newest`, `activeAds`, `newAds`, `euAdsShare`, `reach`, `reach14d`, `followers`. ### 10. Facets — `GET /v1/facets/{categories,technologies,pixels,shopify-apps}` Zero-credit lookups that resolve human-readable filter inputs to the stable ids that `/shops/query`, `/ads/query`, etc. expect. - **Pagination**: `offset` + `limit` (defaults to 100, max 500). - Use the optional `search` query parameter to narrow results before pulling them. ```bash title="Find the skincare category id" curl -s "https://api.trendtrack.io/v1/facets/categories?search=skin&limit=10" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ## Workflow gallery Each workflow ships as a single n8n JSON file at `/integrations/n8n/workflows/.json`. Import via **Workflows → Import from File** in n8n, set the `TRENDTRACK_API_KEY` environment variable, then connect any destination credentials required by the workflow (Slack, Discord, Notion, Google Sheets, Gmail, etc.) before activating. The downloadable files are sanitized examples: they are inactive by default, do not include local n8n workflow ids, do not include pin data, and use placeholder destination ids such as `C0123456789`, `YOUR_GOOGLE_SHEET_ID`, or `YOUR_NOTION_DB_ID` that you must replace. ```bash title="Required n8n environment variable" TRENDTRACK_API_KEY=tt_live_... ``` If you cannot use n8n environment variables, open each Trendtrack HTTP Request node and replace the `Authorization` header expression with `Bearer YOUR_API_KEY`. ### Folder param contract Several gallery workflows start from a tracked brandtracker folder. In those workflows, edit the first **Set Parameters** node and replace `folderName = Demo` with the folder name you use in Trendtrack. - **n/a** — the workflow is per-brand or utility-only; folder scoping doesn't apply. - **Optional folder** — defaults to the whole workspace unless you add filtering. - **Mandatory folder** — the workflow loops over a Trendtrack folder; set `folderName` before the first run. ### 1 — Daily top viral ads → Slack Posts the biggest daily reach movers from your workspace into a Slack channel. - **Trigger**: Cron, daily. - **Endpoint**: `GET /v1/workspace/top-ads` with `sortBy=reachDelta1d` and configurable `limit`. - **Folder param**: n/a in the exported workflow. - **Setup**: Slack credential, `slackChannelId`, optional `limit` and `sortBy` in **Set Parameters**. - **Cost**: about 1 credit per returned ad. - **Download**: [`01-daily-viral-ads.json`](/integrations/n8n/workflows/01-daily-viral-ads.json). ### 2 — Brand lookup → Webhook Utility workflow exposed as an n8n webhook. POST a brand name, domain, Instagram handle, or page id and get back the resolved Trendtrack identifiers. - **Trigger**: Webhook, `POST /webhook/trendtrack-brand-lookup`. - **Endpoint**: `GET /v1/lookup?q={query}&type=auto`. - **Folder param**: n/a. - **Setup**: call the webhook with `{ "q": "allbirds.com" }`, `{ "query": "Cosrx" }`, or `{ "brand": "Cosrx" }`. - **Cost**: 0 credits. - **Download**: [`02-brand-lookup.json`](/integrations/n8n/workflows/02-brand-lookup.json). ### 3 — New ads of brandtracker folder → Discord Polls the brandtrackers in a folder, fetches recent ads for each brand, filters by reach, and posts matching ads to Discord. - **Trigger**: Cron, every 6 hours in the export. - **Endpoints**: `GET /v1/brandtrackers?folderName=...`, then `GET /v1/brandtrackers/{id}/ads`. - **Folder param**: mandatory. Replace `folderName = Demo` in **Set Parameters**. - **Setup**: Discord credential, `discordGuildId`, `discordChannelId`, `reachThreshold`, `lookbackHours`, and max-run guards. - **Cost**: 1 credit per returned ad before filtering. - **Download**: [`03-new-ads-folder.json`](/integrations/n8n/workflows/03-new-ads-folder.json). ### 4 — Weekly creative brief → Notion Builds a weekly markdown digest from the workspace's top ads, hooks, and ad copies, then creates a Notion page. - **Trigger**: Cron, weekly. - **Endpoints**: `GET /v1/workspace/top-ads`, `GET /v1/workspace/hooks`, `GET /v1/workspace/ad-copies`. - **Folder param**: n/a in the exported workflow. - **Setup**: Notion credential, `notionDatabaseId`, and `limit` in **Set Parameters**. - **Cost**: roughly `limit × 3` credits per run. - **Download**: [`04-weekly-creative-brief.json`](/integrations/n8n/workflows/04-weekly-creative-brief.json). ### 5 — Scaling ads alert → Slack Alerts you on Slack when an ad climbs in rank — the canonical "something is taking off" signal. - **Trigger**: Cron, daily. - **Endpoint**: `GET /v1/workspace/top-ads` with `sortBy=rankDelta7d`. - **Folder param**: n/a in the exported workflow. - **Setup**: Slack credential, `slackChannelId`, `minRankDelta`, `topRankThreshold`, and `limit`. - **Cost**: about 1 credit per returned ad. - **Download**: [`05-scaling-alert.json`](/integrations/n8n/workflows/05-scaling-alert.json). ### 6 — Daily top hooks library → Notion Maintains a Notion database of top-performing hooks across the workspace. - **Trigger**: Cron, daily in the export. - **Endpoint**: `GET /v1/workspace/hooks` with configurable `limit`. - **Folder param**: n/a in the exported workflow. - **Setup**: Notion credential, `notionDatabaseId`, and target database properties matching the exported mapping. - **Cost**: 1 credit per returned hook. - **Download**: [`06-top-hooks.json`](/integrations/n8n/workflows/06-top-hooks.json). ### 7 — Shop discovery → Notion candidates Fresh prospecting workflow: resolve a category, query matching shops, filter candidates, and save them to Notion. - **Trigger**: Manual trigger in the export. - **Endpoints**: `GET /v1/facets/categories?search=...`, then `POST /v1/shops/query`. - **Folder param**: n/a. - **Setup**: Notion credential, `categorySearch`, `country`, `minActiveAds`, `limit`, and `notionDatabaseId`. - **Cost**: 4 credits per returned shop. - **Download**: [`07-shop-discovery.json`](/integrations/n8n/workflows/07-shop-discovery.json). ### 8 — Competitor email watch → Slack For every brandtracker in a folder, resolves the primary shop, fetches recent emails since the last run, and posts new campaigns to Slack. - **Trigger**: Cron, daily. - **Endpoints**: `GET /v1/brandtrackers?folderName=...`, `GET /v1/lookup/facebook-shop`, then `GET /v1/shops/{shopId}/emails`. - **Folder param**: mandatory. Replace `folderName = Demo` in **Set Parameters**. - **Setup**: Slack credential, `slackChannelId`, `maxBrandsPerRun`, `maxEmailsPerBrand`. The workflow uses n8n static data to persist `lastEmailCheckAt`. - **Cost**: 2 credits per returned email, plus 1 per brandtracker listed. - **Download**: [`08-competitor-email-watch.json`](/integrations/n8n/workflows/08-competitor-email-watch.json). ### 9 — IG follower tracker → Google Sheets Daily follower tracking for each brandtracker in a folder, appended to Google Sheets, with an optional Slack spike alert. - **Trigger**: Cron, daily. - **Endpoints**: `GET /v1/brandtrackers?folderName=...`, `GET /v1/lookup/facebook-shop`, then `GET /v1/shops/{shopId}/socials/history`. - **Folder param**: mandatory. Replace `folderName = Demo` in **Set Parameters**. - **Setup**: Google Sheets credential, `googleSheetId`, `googleSheetTab`, optional Slack credential and `slackChannelId`, `deltaAlertPct`, and `maxBrandsPerRun`. - **Cost**: 4 credits per brand per run for the history call, plus 1 per brandtracker listed. - **Download**: [`09-ig-follower-tracker.json`](/integrations/n8n/workflows/09-ig-follower-tracker.json). ### 10 — Brand 360 report → Notion + Email On-demand brand report. Fire a webhook with a brand name; the workflow fans out across lookup, overview, top ads, scaling ads, hooks, landing pages, and media mix, then creates a Notion report and emails the link back. - **Trigger**: Webhook, `POST /webhook/trendtrack-brand-report`. - **Endpoints**: `GET /v1/lookup`, `/v1/brandtrackers/{id}/overview`, `/top-ads`, `/scaling-ads`, `/hooks`, `/landing-pages`, `/media-mix`. - **Folder param**: n/a. - **Setup**: Notion credential, Gmail credential, `notionDatabaseId`, and webhook body fields such as `{ "brandName": "Cosrx", "recipientEmail": "team@example.com" }`. - **Cost**: depends on the configured limits across each report section. - **Download**: [`10-brand-360.json`](/integrations/n8n/workflows/10-brand-360.json). ## Cost & rate limits Metered endpoints charge per returned row at their family's rate: 4 credits for shops and products, 3 for advertisers, 2 for emails, 1.5 for Meta ads, 1 for everything else. The relevant headers on every metered response: - `X-Credits-Used` — credits consumed by this request. - `X-Credits-Remaining` — balance after the call. - `X-Credits-Source` — `recurring`, `topup`, or `hybrid`. - `X-Request-Id` — quote when contacting support. A few practical guards while iterating in n8n: - Start every recipe with `limit: 5`–`10` and only raise it once the workflow shape is stable. A loop bug at `limit: 100` burns the workspace. - Pin a daily budget by reading `X-Credits-Remaining` in an `IF` node and breaking the loop below a threshold. - Pagination is **page-based** (`page` + `limit`) on most endpoints, **offset-based** (`offset` + `limit`) on `POST /v1/shops/query` and the `/v1/facets/*` endpoints. Stop paginating when the response returns fewer rows than `limit`. See Credits & Billing for the full consumption model and Rate Limits for `429`/`Retry-After` handling. ## Going further The same patterns apply to **Make.com** and **Zapier** — both have a generic HTTP module with Bearer auth, identical body shapes, and similar pagination handling. For agentic workflows (LLM calls that browse the API live), point your agent at the [Trendtrack Agent Guide](https://docs.trendtrack.io/docs/agent-guide.md) — it carries machine-friendly summaries of every public endpoint, the enum cheatsheet, and the canonical agent traps to avoid. ## FAQ **My calls return `401 missing_api_key` from n8n but `curl` works.** Double-check that the Header Auth credential header name is `Authorization` (not `X-API-Key` or `Authorization-Bearer`) and that the value is `Bearer ` with a space, not just the key. n8n trims newlines but not extra prefixes. **How do I paginate cleanly?** Use a `Split In Batches` loop with the page index, increment until `pagination.totalPages` is reached, and break early when the returned `data.length < limit`. For `/v1/shops/query` and `/v1/facets/*`, increment `offset` by `limit` instead. **I'm hitting `429 rate_limited`.** Read the `Retry-After` response header and feed it into a `Wait` node. Public endpoints are tiered (heavier endpoints have lower per-credential rate caps); see Rate Limits for the exact tiers. **What's the difference between `/v1/brandtrackers/{id}/...` and `/v1/workspace/...`?** Brandtracker endpoints scope to a single tracked brand. Workspace endpoints aggregate across every active brandtracker in the workspace in a single metered call — preferred whenever you'd otherwise loop over brandtrackers and concatenate the results. **Can I filter `/v1/workspace/top-ads` by folder?** Not natively today. The recommended pattern is to call `/v1/workspace/top-ads` and filter the response client-side on `brandtracker.folderId` — applies to current rankings (`sortBy=currentRank`/`reach`) and to rank movers (`sortBy=rankDelta7d`/`14d`/`30d`) alike. The legacy `/v1/workspace/scaling-ads` endpoint still accepts `folderIds` if you need server-side filtering today, but new integrations should standardize on `/v1/workspace/top-ads`. ## Next steps The full bootstrap sequence with response samples and credit-tracking patterns. Header format, key rotation, and what Trendtrack validates on every request. Metered behavior, monthly refill, carry-over, and response headers. Throttling behavior and `Retry-After` handling. Current ranking sort keys vs historical analytics windows. Resource-by-resource operation reference with request and response samples. --- # API Reference Source: https://docs.trendtrack.io/docs/reference/api-reference Use the left sidebar to browse the API by resource area instead of endpoint-by-endpoint. Each resource page lists every operation in that group with request and response samples. ## Jump to a resource Search Shopify stores, pull analytics, and inspect store-level traffic, product, and Meta ad signals. Query Meta/Facebook ad creatives. Filter by status, media type, sort, and pagination. Google Ads and TikTok items live under dedicated resources. Query Google Search, Shopping, Maps, YouTube, and Other ads. Filter by Google category, target country, reach, status, dates, and running time. Search TikTok ads and organic videos with `/v1/tiktok/library`, advanced queries, item detail lookup, and shop-scoped TikTok library discovery. Look up Meta advertiser pages, their active ads, and aggregate performance signals tracked by Trendtrack. List workspace brandtrackers, resolve `brandtrackerId`, start with overview, then use `/top-ads?sortBy=currentRank` for current rank or `rankDelta7d|rankDelta14d|rankDelta30d` for movers. Scaling/ad-rank are legacy compatibility endpoints. Resolve a brand name, domain, Facebook page ID, or Instagram handle via `GET /v1/lookup` and pivot to linked brandtracker, advertiser, and shop resource IDs. Save ads, shops, emails, and advertisers into boards, organize them into collections and folders, archive, restore, and share them. Compatibility layer over boards for existing clients: folder ids are board ids, favorite ids are board item ids. Use Boards for new integrations. Retrieve metadata about the workspace attached to the API key making the call. Check remaining credits, billing period, and metered consumption for the current workspace. Inspect the owner and scopes of the API key presented in the request. Probe public surface endpoints — health, metadata, shell routes, and freshness checks like `GET /v1/system/freshness` before production traffic. Endpoints for email-specific lookups and exports supported by the API. ## Common naming and filtering conventions - Public API base URL: `https://api.trendtrack.io`. - Public query surfaces use canonical sort fields `sortBy` and `order`. - `GET /v1/ads` canonical query param is `search`; deprecated alias `query` is accepted for backward compatibility, but sending both `search` and `query` in one request returns a conflict validation error. Public `/v1/ads*` endpoints are Meta/Facebook-only; use `/v1/google-ads/*` for Google and `/v1/tiktok/*` for TikTok. - `POST /v1/google-ads/query` accepts Google networks `search`, `shopping`, `maps`, `youtube`, and `other`. `categoryIds` uses IDs returned by `/v1/google-ads/facets/categories`; `audienceCountries` filters the countries targeted by the ad, not the advertiser's creation country. Returned Google Ads rows cost one ads credit each. - Use `/v1/tiktok/library`, `/v1/tiktok/library/query`, `/v1/tiktok/library/{itemId}`, and `/v1/shops/{shopId}/tiktok/library` for TikTok ads and organic videos. Returned TikTok library rows are metered one credit per returned item. - `GET /v1/advertisers` supports simple `categoryIds` filters. `POST /v1/advertisers/query` supports either `categoryIds` shorthand or `pageNiches` (not both). Empty `{}` bodies are valid for the POST query endpoint. - `GET /v1/shops` supports `categoryIds`, `pixelIds`, `excludePixelIds`, `shopifyAppIds`, and `excludeShopifyAppIds` filters. Shop responses include additive `tiktok` presence/count fields when indexed; existing `advertising.activeAds`, `latestAds`, and linked advertisers remain Meta/Facebook semantics. - `POST /v1/shops/query` with `searchType: "domain"` performs exact domain/related-domain matching from a domain or URL (no broad wildcard/text fallback). Use `searchType: "shopContains"` for broad website text discovery. - `GET /v1/lookup` returns additive `signals` fields to help disambiguate close matches before metered calls. - `GET /v1/ads/{adId}` serves one ad per duplicate group, with the group's figures. When it serves another ad of the group than the requested one, the response adds `resolvedFrom: { requestedId, reason: "duplicate_group" }`; the field is absent otherwise. - `POST /v1/products/image-search` and `POST /v1/shops/image-search` take a multipart `image` file or a JSON `imageUrl`, then `searchId` + `offset` for the next pages. Results count each shop (or brand, with `groupBrands`) once; see the Search by image guide. - `GET /v1/shops/{shopId}/sales/history` readings each estimate revenue and units over the 30 days before their date, in USD: never sum them. - Workspace top-ads rows are nested objects `{ brandtracker, ad, metrics }` (not a flat ad row). - Folder discovery is available on both `GET /v1/workspace/folders` and `GET /v1/brandtrackers/folders`. - Email endpoints do **not** expose opens/clicks/conversions/revenue metrics. Email sort fields are discovery/indexing sorts, not “best-performing email” KPIs. - For public ad 7-day scaling prompts, use the generated `POST /v1/ads/query` example named “Top ads scaling over the last 7 days” (`sortBy: "reachDelta7d"`, `reachPeriod: "last7d"`, `minReach: 1`) instead of adding first-seen date filters. - For scaling workflows, advertiser `reachDelta7d` sorting is not supported; use supported advertiser sorts (`reach14d`, `activeAds`, etc.) or mover sorts on brandtracker/workspace top-ads. - `reachPeriod` chooses the metric window used by reach/spend thresholds. By itself it does not filter unless paired with `minReach`, `maxReach`, or an endpoint-specific reach sort/filter. - Brandtracker mutations are available through REST and MCP. Destructive MCP tools and REST bulk/folder delete endpoints require `confirm: true`; bulk and folder destructive operations count as one persistent create/delete quota operation while reporting the affected active-link count. - Favorites support `ads`, `shops` (website/shop favorites), and `emails`. Public API endpoints use `/v1/favorites/shops` for website favorites; MCP uses `type: "shops"` for the same resource family. - Favorites scope is explicit: `scope=workspace` reads or writes workspace favorites, while `scope=personal` requires a delegated-user credential. Workspace mutations require writer roles; readonly workspace members can read but cannot create, move, delete, reorder, change visibility, or create share links. - Saved favorite row IDs come from list responses: ads currently use numeric saved-row IDs, shops use `favorite_websites.id` UUIDs, and emails use `favorite_emails.uuid` UUIDs. Email folder IDs and saved email IDs are UUIDs; internal numeric IDs are not public API identifiers. - Folder delete endpoints require explicit contained-item semantics: `delete_items`, `move_items_to_root`, or `move_items_to_folder` with `targetFolderId` when needed. Visibility endpoints switch between `private` and `organization`; private conversion is denied if it would move another user’s contained favorites into personal scope. - Favorite-folder capabilities: ads support items, folders, hierarchy, reorder, and visibility; shops support items, flat folders, and visibility (no hierarchy or reorder); emails support items, folders, hierarchy, reorder, and visibility. - Share links are ads-focused: `POST /v1/ads/{adId}/share` creates or returns a raw ad share URL, and `POST /v1/favorites/ads/folders/{folderId}/share` creates or returns a favorite ad folder share URL. Shop/email share links are not exposed. ## Favorites REST examples ```bash title="List saved email favorites" curl "https://api.trendtrack.io/v1/favorites/emails?scope=workspace&limit=10" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ```bash title="Create a shop favorite folder" curl -X POST "https://api.trendtrack.io/v1/favorites/shops/folders" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"scope":"workspace","name":"Competitor shops"}' ``` ```bash title="Delete an ad favorite folder and move contained ads to root" curl -X DELETE "https://api.trendtrack.io/v1/favorites/ads/folders/00000000-0000-0000-0000-000000000000?scope=workspace" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mode":"move_items_to_root"}' ``` ```bash title="Create a favorite ad folder share link" curl -X POST "https://api.trendtrack.io/v1/favorites/ads/folders/00000000-0000-0000-0000-000000000000/share?scope=workspace" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ## TikTok REST examples ```bash title="List TikTok library items" curl "https://api.trendtrack.io/v1/tiktok/library?search=collagen%20gummies&type=all&limit=10" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ```bash title="Advanced TikTok library query" curl -X POST "https://api.trendtrack.io/v1/tiktok/library/query" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"search":["collagen gummies"],"searchArea":"caption","type":"ad","status":"active","sortBy":"views","order":"desc","limit":10}' ``` ```bash title="Get one TikTok library item" curl "https://api.trendtrack.io/v1/tiktok/library/tiktok_7078586231734521093" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ```bash title="List TikTok library items for a shop" curl "https://api.trendtrack.io/v1/shops/3f8aa146-6f96-46e8-9781-64db5166f9a8/tiktok/library?type=all&limit=10" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ## Google Ads REST examples ```bash title="Discover Google category IDs" curl "https://api.trendtrack.io/v1/google-ads/facets/categories?search=clothing&limit=10" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" ``` ```bash title="Query US Shopping ads by Google category" curl -X POST "https://api.trendtrack.io/v1/google-ads/query" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "active", "networks": ["shopping"], "categoryIds": [24], "audienceCountries": { "include": ["US"] }, "sortBy": "newest", "order": "desc", "page": 1, "limit": 10 }' ``` ```bash title="Search Google advertisers and filter by ad reach" curl -X POST "https://api.trendtrack.io/v1/google-ads/query" \ -H "Authorization: Bearer $TRENDTRACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "search": ["nike"], "status": "active", "minReach": 1000, "maxReach": 1000000, "sortBy": "reach", "order": "desc", "page": 1, "limit": 10 }' ``` ## Recommended workflow 1. Start with Getting Started to obtain a key and make a first call. 2. Confirm Authentication so every subsequent request carries `Authorization: Bearer `. 3. For brand/domain/Facebook page ID/Instagram handle questions, call `GET /v1/lookup?q=...` first (zero-credit), then pivot to the linked `brandtracker`, `advertiser`, or `shop` resource IDs. 4. For tracked-brand deep dives, use `GET /v1/brandtrackers/{brandtrackerId}/overview` first. 5. For rankings, use canonical top-ads calls: `GET /v1/brandtrackers/{brandtrackerId}/top-ads?sortBy=currentRank` or `GET /v1/workspace/top-ads?sortBy=currentRank`. 6. For rank movers, use `sortBy=rankDelta7d`, `rankDelta14d`, or `rankDelta30d`; use `reach`, `reachDelta1d`, `reachDelta7d`, or `reachDelta30d` for reach rankings. 7. Treat `/scaling-ads` and `/ad-rank` as legacy compatibility endpoints; their ES-backed responses may return an empty `trajectory`. 8. For freshness-sensitive historical workflows, check `GET /v1/system/freshness` (global) and `GET /v1/brandtrackers/{brandtrackerId}/snapshots` (brandtracker-level readiness). 9. Keep Credits & Billing, Rate Limits, and Errors open while integrating — you will hit them. 10. Drill into the resource pages above (or the sidebar) for the exact request shape of each operation, including brandtracker create-by-domain/shop aliases, folders, and workspace-link move/delete operations. The API reference does not ship a hosted playground. Copy the request sample on each operation, swap in your bearer API key, and run it from your own terminal or HTTP client. This keeps the reference fast to scan and avoids surprise network calls while you read. Return to the docs overview for the guided entry point. --- # API Reference The following sections document every endpoint exposed by the TrendTrack public API, one entry per operation. Only success responses are shown — every endpoint returns the same error body `{ error: { code, message } }` on 4xx/5xx. See https://docs.trendtrack.io/docs/guides/errors for the full list of error codes. --- Tag: System · Reference: https://docs.trendtrack.io/docs/reference/api/system#get-public-api-metadata # Get public API metadata `GET /v1` Returns a minimal bootstrap payload describing the current Trendtrack Public API version and status. **Tags:** System ## Responses ### 200 - Public API metadata. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | Yes | Public API product name. | | `version` | `string` | Yes | Current public API version. | | `status` | `string` | Yes | Bootstrap health indicator. | --- Tag: System · Reference: https://docs.trendtrack.io/docs/reference/api/system#check-public-api-health # Check public API health `GET /v1/health` Returns a lightweight health payload for the public bootstrap mounted under /v1. **Tags:** System ## Responses ### 200 - Public bootstrap health snapshot. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `status` | `string` | Yes | Health status for the public bootstrap. | | `timestamp` | `string` | Yes | ISO timestamp captured when the health check was served. | | `uptime` | `number` | Yes | Process uptime in seconds. | --- Tag: System · Reference: https://docs.trendtrack.io/docs/reference/api/system#read-public-api-data-freshness # Read public API data freshness `GET /v1/system/freshness` Returns the latest ready and latest indexed/scheduled global snapshot dates for public API reach-history data. **Tags:** System ## Responses ### 200 - Global public API data freshness payload. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `status` | `string` | Yes | System freshness endpoint status. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `latestReadyDate` | `string` | Yes | Latest global snapshot date with usable reach rows, or null when none exists. | | `latestScheduledDate` | `string` | Yes | Latest global indexed/scheduled snapshot date observed in reach history, even if not ready yet. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and latestReadyDate. Null when no ready snapshot exists. | | `generatedAt` | `string` | Yes | ISO timestamp captured when this freshness payload was generated. | --- Tag: Identity · Reference: https://docs.trendtrack.io/docs/reference/api/identity#resolve-the-current-api-credential # Resolve the current API credential `GET /v1/me` Returns the workspace, credential, and delegated user context resolved from the provided public API key. **Tags:** Identity ## Responses ### 200 - Resolved public API identity payload. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `credential` | `object` | Yes | | | `workspace` | `object` | Yes | | | `delegatedUser` | `object` | Yes | Delegated user context when the credential access level is delegated_user. | **`credential` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `description` | `string` | Yes | Optional credential description. | | `accessLevel` | `full_access` \| `delegated_user` | Yes | | | `expiresAt` | `string` | Yes | Credential expiration timestamp when configured. | | `createdAt` | `string` | Yes | | | `lastUsedAt` | `string` | Yes | | **`workspace` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `slug` | `string` | Yes | | | `name` | `string` | Yes | | | `createdAt` | `string` | Yes | | **`delegatedUser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `fullName` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `workspaceRole` | `owner` \| `admin` \| `member` \| `readonly` | Yes | | --- Tag: Usage · Reference: https://docs.trendtrack.io/docs/reference/api/usage#read-the-current-workspace-usage-snapshot # Read the current workspace usage snapshot `GET /v1/usage` Returns the current public API billing, included quota, and credit balance snapshot for the authenticated workspace. **Tags:** Usage ## Responses ### 200 - Current usage snapshot for the authenticated workspace. The response also includes the X-Request-Id, X-Usage-Cost, X-Credits-Used, and X-Credits-Remaining headers. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `workspace` | `object` | Yes | | | `credential` | `object` | Yes | | | `billing` | `object` | Yes | | | `includedQuota` | `object` | Yes | Deprecated compatibility block. Use credits.recurring and credits.totalRemaining instead. | | `credits` | `object` | Yes | | **`workspace` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `slug` | `string` | Yes | | | `name` | `string` | Yes | | **`credential` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `accessLevel` | `full_access` \| `delegated_user` | Yes | | | `lastUsedAt` | `string` | Yes | | **`billing` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `configured` | `boolean` | Yes | Whether the workspace currently has billing configuration for the public API. | | `planCode` | `string` | Yes | Current billing plan code when configured. | | `currentPeriodStart` | `string` | Yes | | | `currentPeriodEnd` | `string` | Yes | | | `updatedAt` | `string` | Yes | | **`includedQuota` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `used` | `number` | Yes | | | `remaining` | `number` | Yes | | **`credits` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `balance` | `number` | Yes | Deprecated compatibility alias of credits.topup.balance. | | `recurring` | `object` | Yes | | | `topup` | `object` | Yes | | | `totalRemaining` | `number` | Yes | Total remaining recurring + top-up credits. | **`recurring` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `used` | `number` | Yes | | | `remaining` | `number` | Yes | | **`topup` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `balance` | `number` | Yes | | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#list-workspace-brandtracker-folders # List workspace brandtracker folders `GET /v1/workspace/folders` Returns the active workspace brandtracker folders so clients can resolve folderIds for workspace and brandtracker filters. Folder names are returned as metadata; prefer folderIds for exact filtering. Equivalent folder listing is also available at GET /v1/brandtrackers/folders. **Tags:** Workspace ## Responses ### 200 - Workspace brandtracker folders. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `rank` | `number` | Yes | | | `brandtrackerCount` | `number` | Yes | Number of active brandtrackers currently assigned to this folder. | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#inspect-the-authenticated-workspace # Inspect the authenticated workspace `GET /v1/workspace` Returns the workspace bound to the provided public API key along with the effective authentication context. **Tags:** Workspace ## Responses ### 200 - Workspace snapshot for the authenticated public API credential. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `workspace` | `object` | Yes | | | `authenticatedAs` | `object` | Yes | | | `credential` | `object` | Yes | | **`workspace` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `slug` | `string` | Yes | | | `name` | `string` | Yes | | | `createdAt` | `string` | Yes | | **`authenticatedAs` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `accessLevel` | `full_access` \| `delegated_user` | Yes | | | `delegatedUserId` | `string` | Yes | Delegated user identifier when authenticated with a delegated credential. | | `delegatedUserRole` | `owner` \| `admin` \| `member` \| `readonly` | Yes | Workspace role of the delegated user when present. | **`credential` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `description` | `string` | Yes | | | `expiresAt` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `lastUsedAt` | `string` | Yes | | --- Tag: Facets · Reference: https://docs.trendtrack.io/docs/reference/api/facets#list-public-category-facets # List public category facets `GET /v1/facets/categories` Returns Google taxonomy category IDs currently available for public API category filters across shops, ads, emails, and advertisers. **Tags:** Facets ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | Case-insensitive substring search over the facet label fields. | | `limit` | query | No | `integer` | | | `offset` | query | No | `integer` | | ## Responses ### 200 - Category facet values with pagination and filter usage metadata. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `valueType` | `number` \| `uuid` \| `slug` | Yes | | | `filterUsage` | `object`[] | Yes | | **`filterUsage[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `resource` | `shops` \| `ads` \| `emails` \| `advertisers` | Yes | | | `fields` | `string`[] | Yes | | | `valueField` | `id` \| `slug` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `path` | `string` | Yes | | | `parentId` | `number` | Yes | | | `usageCount` | `number` | Yes | | --- Tag: Facets · Reference: https://docs.trendtrack.io/docs/reference/api/facets#list-public-shopify-app-facets # List public Shopify app facets `GET /v1/facets/shopify-apps` Returns grouped Shopify app IDs currently available for public API Shopify app filters on shops and ads. **Tags:** Facets ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | Case-insensitive substring search over the facet label fields. | | `limit` | query | No | `integer` | | | `offset` | query | No | `integer` | | ## Responses ### 200 - Shopify app facet values with pagination and filter usage metadata. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `valueType` | `number` \| `uuid` \| `slug` | Yes | | | `filterUsage` | `object`[] | Yes | | **`filterUsage[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `resource` | `shops` \| `ads` \| `emails` \| `advertisers` | Yes | | | `fields` | `string`[] | Yes | | | `valueField` | `id` \| `slug` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `label` | `string` | Yes | | | `iconUrl` | `string` | Yes | | | `shopifyUrl` | `string` | Yes | | | `usageCount` | `number` | Yes | | --- Tag: Facets · Reference: https://docs.trendtrack.io/docs/reference/api/facets#list-public-technology-facets # List public technology facets `GET /v1/facets/technologies` Returns supported technology slugs accepted by public API technology filters, enriched with metadata when available. **Tags:** Facets ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | Case-insensitive substring search over the facet label fields. | | `limit` | query | No | `integer` | | | `offset` | query | No | `integer` | | ## Responses ### 200 - Technology facet values with pagination and filter usage metadata. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `valueType` | `number` \| `uuid` \| `slug` | Yes | | | `filterUsage` | `object`[] | Yes | | **`filterUsage[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `resource` | `shops` \| `ads` \| `emails` \| `advertisers` | Yes | | | `fields` | `string`[] | Yes | | | `valueField` | `id` \| `slug` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `slug` | `string` | Yes | | | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `iconUrl` | `string` | Yes | | | `categories` | `string`[] | Yes | | | `usageCount` | `number` | Yes | | --- Tag: Facets · Reference: https://docs.trendtrack.io/docs/reference/api/facets#list-public-pixel-facets # List public pixel facets `GET /v1/facets/pixels` Returns pixel technology UUIDs currently available for public API pixel filters on shops and ads. **Tags:** Facets ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | Case-insensitive substring search over the facet label fields. | | `limit` | query | No | `integer` | | | `offset` | query | No | `integer` | | ## Responses ### 200 - Pixel facet values with pagination and filter usage metadata. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `valueType` | `number` \| `uuid` \| `slug` | Yes | | | `filterUsage` | `object`[] | Yes | | **`filterUsage[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `resource` | `shops` \| `ads` \| `emails` \| `advertisers` | Yes | | | `fields` | `string`[] | Yes | | | `valueField` | `id` \| `slug` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `slug` | `string` | Yes | | | `name` | `string` | Yes | | | `iconUrl` | `string` | Yes | | | `categories` | `string`[] | Yes | | | `usageCount` | `number` | Yes | | --- Tag: Facets · Reference: https://docs.trendtrack.io/docs/reference/api/facets#list-public-shopify-theme-facets # List public Shopify theme facets `GET /v1/facets/themes` Returns Shopify theme UUIDs currently available for public API theme filters on shops. **Tags:** Facets ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | Case-insensitive substring search over the facet label fields. | | `limit` | query | No | `integer` | | | `offset` | query | No | `integer` | | ## Responses ### 200 - Theme facet values with pagination and filter usage metadata. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `valueType` | `number` \| `uuid` \| `slug` | Yes | | | `filterUsage` | `object`[] | Yes | | **`filterUsage[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `resource` | `shops` \| `ads` \| `emails` \| `advertisers` | Yes | | | `fields` | `string`[] | Yes | | | `valueField` | `id` \| `slug` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `usageCount` | `number` | Yes | | --- Tag: Discovery · Reference: https://docs.trendtrack.io/docs/reference/api/discovery#resolve-a-brand-advertiser-or-shop # Resolve a brand, advertiser, or shop `GET /v1/lookup` Zero-credit lookup for brand names, shop domains, Facebook page ids, and Instagram handles. Exact matches are returned before fuzzy name matches. **Tags:** Discovery ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `q` | query | Yes | `string` | Brand name, shop domain, Facebook page id, or Instagram handle. | | `type` | query | No | `auto` \| `brandtracker` \| `advertiser` \| `shop` | Limit lookup to one resource type, or search brandtrackers, advertisers, and shops with auto. | | `limit` | query | No | `integer` | | ## Responses ### 200 - Lookup results linking known brandtracker, advertiser, and shop public identifiers. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `brandtracker` \| `advertiser` \| `shop` | Yes | | | `matchType` | `exact` \| `fuzzy` | Yes | | | `matchField` | `name` \| `domain` \| `facebookPageId` \| `instagramHandle` | Yes | | | `score` | `number` | Yes | Lookup confidence score. Exact identifier/domain/name matches return 1; fuzzy candidates return lower scores. | | `brandtracker` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `shop` | `object` | Yes | | | `signals` | `object` | Yes | Additive disambiguation signals derived from existing lookup candidate ranking/resource metadata. | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | **`signals` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | Active ads signal when available from lookup candidate ranking metadata. | | `liveAdsCount` | `number` | Yes | Live ads signal alias when available (same source as activeAds when only one is present). | | `reach30d` | `number` | Yes | 30-day reach signal when available from lookup ranking metadata. | | `totalReach` | `number` | Yes | Total/current reach signal when available from lookup ranking metadata. | | `monthlyVisits` | `number` | Yes | Monthly visits signal when available from lookup candidate ranking metadata. | | `workspaceAddedAt` | `string` | Yes | Workspace-added timestamp signal when available from lookup candidate ranking metadata. | | `hasBrandtracker` | `boolean` | Yes | | | `hasAdvertiser` | `boolean` | Yes | | | `hasShop` | `boolean` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `q` | `string` | Yes | | | `type` | `auto` \| `brandtracker` \| `advertiser` \| `shop` | Yes | | | `limit` | `number` | Yes | | | `returned` | `number` | Yes | | | `partial` | `boolean` | No | Present when type=auto returned successful resource matches while one or more lookup branches timed out. | | `warnings` | `array`[] | No | | --- Tag: Discovery · Reference: https://docs.trendtrack.io/docs/reference/api/discovery#resolve-facebook-page-and-shop-relationships # Resolve Facebook page and shop relationships `GET /v1/lookup/facebook-shop` Zero-credit resolver for deterministic Facebook page ↔ shop/site relationships. Provide exactly one Facebook page alias or one shop/site alias. **Tags:** Discovery ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `facebook_id` | query | No | `string` | Facebook page id alias. Provide one Facebook page alias or one shop/site alias. | | `facebookPageId` | query | No | `string` | Facebook page id alias. Provide one Facebook page alias or one shop/site alias. | | `fb_page_id` | query | No | `string` | Facebook page id alias. Provide one Facebook page alias or one shop/site alias. | | `shopId` | query | No | `string` | Shop/site id alias. Provide one shop/site alias or one Facebook page alias. | | `website_id` | query | No | `string` | Shop/site id alias. Provide one shop/site alias or one Facebook page alias. | | `limit` | query | No | `integer` | | ## Responses ### 200 - Ordered linked shops or Facebook pages, with a primary relationship convenience field. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `meta` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `input` | `object` | Yes | | | `primaryShop` | `object` | Yes | | | `shops` | `object`[] | Yes | | | `primaryFacebookPage` | `object` | Yes | | | `facebookPages` | `object`[] | Yes | | **`input` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `facebookPage` \| `shop` | Yes | | | `id` | `string` | Yes | | **`primaryShop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `rank` | `string` | Yes | | | `isMainRelation` | `boolean` | Yes | | | `isPrimary` | `boolean` | Yes | | | `trafficNumber` | `number` | Yes | | | `profilePhotoUrl` | `string` | Yes | | **`shops[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `rank` | `string` | Yes | | | `isMainRelation` | `boolean` | Yes | | | `isPrimary` | `boolean` | Yes | | | `trafficNumber` | `number` | Yes | | | `profilePhotoUrl` | `string` | Yes | | **`primaryFacebookPage` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `rank` | `string` | Yes | | | `isMainRelation` | `boolean` | Yes | | | `isPrimary` | `boolean` | Yes | | | `runningAds` | `number` | Yes | | **`facebookPages[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `rank` | `string` | Yes | | | `isMainRelation` | `boolean` | Yes | | | `isPrimary` | `boolean` | Yes | | | `runningAds` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `returnedShops` | `number` | Yes | | | `returnedFacebookPages` | `number` | Yes | | --- Tag: Advertisers · Reference: https://docs.trendtrack.io/docs/reference/api/advertisers#list-advertisers # List advertisers `GET /v1/advertisers` Returns the lightweight public advertisers collection. This endpoint stays intentionally simple and focuses on brand/domain search, pagination, ordering, and stable scalar filters. Use POST /v1/advertisers/query for the advanced discovery surface. **Tags:** Advertisers ## Parameters **Query parameter groups:** - Pagination: `offset`, `limit` - Search: `search`, `searchType`, `keywordMode` - Time and snapshots: `minFbPageCreationDate`, `maxFbPageCreationDate`, `adsTimePeriod`, `adsLaunchedPeriod`, `reachPeriod` - Sorting: `sortBy`, `order` - Filters: `minActiveAds`, `maxActiveAds`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minAdsLaunched`, `maxAdsLaunched`, `minReach`, `maxReach`, `pageType`, `categoryIds`, `shopifyLinked`, `gender` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string`[] | Optional advertiser search keywords. Repeated query params and comma-separated values are both accepted. | | `searchType` | query | No | `brand` \| `domain` | Simple search strategy for the advertisers collection. Use POST /v1/advertisers/query for advanced text resolution modes. | | `keywordMode` | query | No | `any` \| `all` | How multiple search keywords should combine. Defaults to any. | | `sortBy` | query | No | `relevance` \| `newest` \| `activeAds` \| `newAds` \| `euAdsShare` \| `reach` \| `reach14d` \| `followers` | Primary sort key for advertiser discovery. Defaults to relevance. | | `order` | query | No | `asc` \| `desc` | Sort order. Ignored when sortBy=relevance because relevance is always ranked descending. | | `offset` | query | No | `integer` | Pagination offset. Defaults to 0. | | `limit` | query | No | `integer` | Maximum number of advertisers to return. Defaults to 20. | | `minFbPageCreationDate` | query | No | `string` | Inclusive lower bound for the Facebook page creation date filter. | | `maxFbPageCreationDate` | query | No | `string` | Inclusive upper bound for the Facebook page creation date filter. | | `minActiveAds` | query | No | `integer` | | | `maxActiveAds` | query | No | `integer` | | | `adsTimePeriod` | query | No | `current` \| `last24h` \| `last7d` \| `last14d` \| `last30d` | Enum value accepted by this request. Allowed values: `current`, `last24h`, `last7d`, `last14d`, `last30d`. | | `minFacebookLikes` | query | No | `integer` | | | `maxFacebookLikes` | query | No | `integer` | | | `minInstagramFollowers` | query | No | `integer` | | | `maxInstagramFollowers` | query | No | `integer` | | | `minAdsLaunched` | query | No | `integer` | | | `maxAdsLaunched` | query | No | `integer` | | | `adsLaunchedPeriod` | query | No | `last24h` \| `last7d` \| `last14d` \| `last30d` \| `last90d` | Time window accepted by this request. Allowed values: `last24h`, `last7d`, `last14d`, `last30d`, `last90d`. | | `minReach` | query | No | `integer` | Minimum advertiser reach threshold. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `maxReach` | query | No | `integer` | Maximum advertiser reach threshold. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `reachPeriod` | query | No | `last24h` \| `last7d` \| `last14d` \| `last30d` \| `last90d` \| `total` | Reach/impressions metric window. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. Allowed values: `last24h`, `last7d`, `last14d`, `last30d`, `last90d`, `total`. | | `pageType` | query | No | `influencer` \| `brand`[] | Enum value accepted by this request. Allowed values: `influencer`, `brand`. | | `categoryIds` | query | No | `integer`[] | Google category facet ids matched through linked websites' website_overview.google_categories. Repeated query params and comma-separated values are both accepted. | | `shopifyLinked` | query | No | `yes` \| `no` \| `all` | Filter by indexed linked-site Shopify technology. `no` means no indexed Shopify technology is present for the advertiser. | | `gender` | query | No | `male` \| `female` \| `all` | Enum value accepted by this request. Allowed values: `male`, `female`, `all`. | ## Responses ### 200 - Paginated advertisers response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Current public advertiser identifier. This MVP uses the Facebook page id directly. | | `platform` | `facebook` | Yes | | | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `profile` | `object` | Yes | | | `advertising` | `object` | Yes | | | `lastAds` | `object`[] | Yes | | | `mainLandingPages` | `object`[] | Yes | | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `likes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | | `createdAt` | `string` | Yes | Facebook/page-explorer page creation date, aligned with minFbPageCreationDate and maxFbPageCreationDate filters. This is not the internal database ingestion timestamp. | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | Active ads count, preferring page-explorer running_ads_count with relational fallback when unavailable. | | `reach30d` | `number` | Yes | Advertiser reach over the last 30 days, preferring page-explorer eu_reach_30d with fb_page fallback when unavailable. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | **`lastAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | **`mainLandingPages[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `landingPage` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isTruncated` | `boolean` | Yes | True when an intermediary aggregation-based search stage truncated the intermediate id set before the final advertiser query. | --- Tag: Advertisers · Reference: https://docs.trendtrack.io/docs/reference/api/advertisers#query-advertisers # Query advertisers `POST /v1/advertisers/query` Returns the advanced public advertisers query surface. This endpoint supports the current richer advertiser discovery filters through a structured public camelCase contract while keeping the response aligned with the standard public advertiser summary shape. categoryIds uses linked websites' google_categories; pageNiches remains an advanced legacy page-niche filter. Empty JSON bodies are valid and use defaults. **Tags:** Advertisers ## Request Body **Content-Type:** `application/json` **Find active brand advertisers with strong recent reach:** ```json { "search": [ "athleisure" ], "searchType": "brand", "sortBy": "reach", "order": "desc", "adsTimePeriod": "last7d", "minActiveAds": 10, "reachPeriod": "last14d", "minReach": 50000, "categoryIds": [ 254 ], "pageType": [ "brand" ], "limit": 20, "offset": 0 } ``` **Empty object body is valid and uses default pagination/sort behavior:** ```json {} ``` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `search` | `string`[] | No | | | `searchType` | `brand` \| `domain` \| `adCopy` \| `websiteCopy` \| `urlContains` | No | Advanced search strategy for advertiser discovery. Supports content and URL resolution modes in addition to simple brand/domain search. | | `keywordMode` | `any` \| `all` | No | Enum value accepted by this request. Allowed values: `any`, `all`. | | `sortBy` | `relevance` \| `newest` \| `activeAds` \| `newAds` \| `euAdsShare` \| `reach` \| `reach14d` \| `followers` | No | Sort key for this request. Allowed values: `relevance`, `newest`, `activeAds`, `newAds`, `euAdsShare`, `reach`, `reach14d`, `followers`. | | `order` | `asc` \| `desc` | No | Sort order. Ignored when sortBy=relevance because relevance is always ranked descending. | | `offset` | `number` | No | | | `limit` | `number` | No | | | `minFbPageCreationDate` | `string` | No | | | `maxFbPageCreationDate` | `string` | No | | | `minActiveAds` | `number` | No | | | `maxActiveAds` | `number` | No | | | `adsTimePeriod` | `current` \| `last24h` \| `last7d` \| `last14d` \| `last30d` | No | Enum value accepted by this request. Allowed values: `current`, `last24h`, `last7d`, `last14d`, `last30d`. | | `minFacebookLikes` | `number` | No | | | `maxFacebookLikes` | `number` | No | | | `minInstagramFollowers` | `number` | No | | | `maxInstagramFollowers` | `number` | No | | | `minAdsLaunched` | `number` | No | | | `maxAdsLaunched` | `number` | No | | | `adsLaunchedPeriod` | `last24h` \| `last7d` \| `last14d` \| `last30d` \| `last90d` | No | Time window accepted by this request. Allowed values: `last24h`, `last7d`, `last14d`, `last30d`, `last90d`. | | `minReach` | `number` | No | Minimum advertiser reach threshold. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `maxReach` | `number` | No | Maximum advertiser reach threshold. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `reachPeriod` | `last24h` \| `last7d` \| `last14d` \| `last30d` \| `last90d` \| `total` | No | Reach/impressions metric window. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. Allowed values: `last24h`, `last7d`, `last14d`, `last30d`, `last90d`, `total`. | | `minSpendPerPage` | `number` | No | Minimum estimated spend per page. Converted internally through CPM and reach/impressions fields. | | `maxSpendPerPage` | `number` | No | Maximum estimated spend per page. Converted internally through CPM and reach/impressions fields. | | `spendPerPagePeriod` | `last24h` \| `last7d` \| `last14d` \| `last30d` \| `last90d` \| `total` | No | Reach/impressions metric window. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. Allowed values: `last24h`, `last7d`, `last14d`, `last30d`, `last90d`, `total`. | | `cpm` | `number` | No | CPM used to convert spend filters into reach/impressions-based ES ranges. | | `minReachPerPage` | `number` | No | Minimum reach-per-page filter. Reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `maxReachPerPage` | `number` | No | Maximum reach-per-page filter. Reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachPerPagePeriod` | `last24h` \| `last7d` \| `last14d` \| `last30d` \| `last90d` \| `total` | No | Reach/impressions metric window. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. Allowed values: `last24h`, `last7d`, `last14d`, `last30d`, `last90d`, `total`. | | `adLanguage` | `string`[] | No | | | `technologies` | `string`[] | No | | | `adCountries` | `object` | No | Countries where the advertiser is distributing ads. Uses ISO 3166-1 alpha-2 country codes. | | `mainCountries` | `string`[] | No | Primary countries to match. | | `countryFilterMode` | `reach` \| `adCount` | No | Enum value accepted by this request. Allowed values: `reach`, `adCount`. | | `adsGrowth` | `object` | No | Ads growth filter. Uses OR groups (`anyOf`) made of AND-ed rules (`all`), with rule fields `period`, `operator`, and `value`. | | `pageReachGrowth` | `object` | No | Page reach growth filter. Uses OR groups (`anyOf`) made of AND-ed rules (`all`), with rule fields `period`, `operator`, and `value`. | | `ageRanges` | `string`[] | No | | | `pageType` | `influencer` \| `brand`[] | No | Enum value accepted by this request. Allowed values: `influencer`, `brand`. | | `categoryIds` | `number`[] | No | Google category facet ids matched through linked websites' website_overview.google_categories. | | `pageNiches` | `object` | No | Not supported: advertiser page niches are not indexed, so any non-empty selection is rejected with 400 unsupported_filter. Use categoryIds, which matches linked websites via google_categories. | | `minPartnershipPercentage` | `number` | No | | | `shopifyLinked` | `yes` \| `no` \| `all` | No | Filter by indexed linked-site Shopify technology. `no` means no indexed Shopify technology is present for the advertiser. | | `gender` | `male` \| `female` \| `all` | No | Enum value accepted by this request. Allowed values: `male`, `female`, `all`. | **`adCountries` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `include` | `string`[] | No | ISO 3166-1 alpha-2 country codes to include. | | `exclude` | `string`[] | No | ISO 3166-1 alpha-2 country codes to exclude. | **`adsGrowth` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | OR groups of ads growth rules. Each group combines its rules with AND. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`pageReachGrowth` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | OR groups of page reach growth rules. Each group combines its rules with AND. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`pageNiches` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `main` | `number`[] | No | Advanced legacy page-niche categories that must match the main advertiser page niche. | | `among` | `number`[] | No | Advanced legacy page-niche categories that may appear among advertiser page niches. | | `exclude` | `number`[] | No | Advanced legacy page-niche categories to exclude from advertiser page niches. | ## Responses ### 200 - Paginated advertisers query response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Current public advertiser identifier. This MVP uses the Facebook page id directly. | | `platform` | `facebook` | Yes | | | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `profile` | `object` | Yes | | | `advertising` | `object` | Yes | | | `lastAds` | `object`[] | Yes | | | `mainLandingPages` | `object`[] | Yes | | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `likes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | | `createdAt` | `string` | Yes | Facebook/page-explorer page creation date, aligned with minFbPageCreationDate and maxFbPageCreationDate filters. This is not the internal database ingestion timestamp. | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | Active ads count, preferring page-explorer running_ads_count with relational fallback when unavailable. | | `reach30d` | `number` | Yes | Advertiser reach over the last 30 days, preferring page-explorer eu_reach_30d with fb_page fallback when unavailable. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | **`lastAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | **`mainLandingPages[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `landingPage` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isTruncated` | `boolean` | Yes | True when an intermediary aggregation-based search stage truncated the intermediate id set before the final advertiser query. | --- Tag: Advertisers · Reference: https://docs.trendtrack.io/docs/reference/api/advertisers#list-ads-for-an-advertiser # List ads for an advertiser `GET /v1/advertisers/{advertiserId}/ads` Returns a paginated list of ads for the requested page-centric advertiser. In this first MVP iteration, advertiserId resolves directly from the Facebook page id. **Tags:** Advertisers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `advertiserId` | path | Yes | `string` | Public advertiser identifier. Current MVP uses the Facebook page id directly. | | `limit` | query | No | `integer` | | | `offset` | query | No | `integer` | | | `status` | query | No | `all` \| `active` \| `inactive` | Filter ads by activity status. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Filter ads by creative media type. Allowed values: `all`, `image`, `video`. | | `sortBy` | query | No | `newest` \| `createdAt` \| `longestRunning` \| `reach` \| `duplicates` | Sort key for advertiser ads. `reach` uses the public reach/impressions metric; no `impressions` alias is accepted on this endpoint. | | `order` | query | No | `asc` \| `desc` | Sort direction. Allowed values: `asc`, `desc`. | | `cpm` | query | No | `integer` | Optional CPM override used to compute estimated spend in the ads response. | ## Responses ### 200 - Paginated advertiser ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | --- Tag: Advertisers · Reference: https://docs.trendtrack.io/docs/reference/api/advertisers#get-advertiser-detail # Get advertiser detail `GET /v1/advertisers/{advertiserId}` Returns the page-centric advertiser detail. In this first MVP iteration, advertiserId resolves directly from the Facebook page id. **Tags:** Advertisers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `advertiserId` | path | Yes | `string` | Public advertiser identifier. Current MVP uses the Facebook page id directly. | ## Responses ### 200 - Advertiser detail response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Current MVP uses the Facebook page id directly as the public advertiser id. | | `platform` | `facebook` | Yes | | | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `profile` | `object` | Yes | | | `linkedShops` | `object`[] | Yes | | | `advertising` | `object` | Yes | | | `lastAds` | `object`[] | Yes | Most recent advertiser ads using the shared public ad summary contract. | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `likes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | | `createdAt` | `string` | Yes | Facebook/page-explorer page creation date, aligned with minFbPageCreationDate and maxFbPageCreationDate filters. This is not the internal database ingestion timestamp. | **`linkedShops[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shopId` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `isPrimary` | `boolean` | Yes | | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | Active ads count, preferring page-explorer running_ads_count with relational fallback when unavailable. | | `reach30d` | `number` | Yes | Advertiser reach over the last 30 days, preferring page-explorer eu_reach_30d with fb_page.impressions_last_month fallback when unavailable. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countryDistribution` | `object`[] | Yes | | **`countryDistribution[]` item properties:** **`lastAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#list-ads # List ads `GET /v1/ads` Returns the lightweight public ads collection. This endpoint stays intentionally small and focuses on text search, brand search, simple filters, sorting, and pagination. The search parameter is required; for advanced filtering without a required text search, use POST /v1/ads/query. **Tags:** Ads ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `search`, `searchType`, `query` - Sorting: `sortBy` - Filters: `platform`, `status`, `mediaType` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | Yes | `string` | Canonical text query for the lightweight public ads listing. | | `searchType` | query | No | `adCopy` \| `brand` | Search mode for this request. Allowed values: `adCopy`, `brand`. | | `platform` | query | No | `facebook` \| `all` | Enum value accepted by this request. Allowed values: `facebook`, `all`. TikTok is not available in public v1. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `status` | query | No | `active` \| `inactive` \| `all` | Status filter for this request. Allowed values: `active`, `inactive`, `all`. | | `mediaType` | query | No | `image` \| `video` \| `carousel` | Creative media type filter for this request. Allowed values: `image`, `video`, `carousel`. `carousel` maps to indexed carousel creatives and is not a DCO filter. | | `sortBy` | query | No | `relevance` \| `newest` \| `longestRunning` \| `reach` | Sort key for this request. Allowed values: `relevance`, `newest`, `longestRunning`, `reach`. | | `query` | query | No | `string` | Deprecated alias for search. Use search instead. | ## Responses ### 200 - Paginated ads response using the public ads contract. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#query-ads # Query ads `POST /v1/ads/query` Returns the advanced public ads query surface. This endpoint supports the full current ads filtering set through a public camelCase contract with structured JSON for advanced growth, country, market, and ranking filters while keeping the response aligned with the standard public ad summary shape. Search terms are optional in this route. **Tags:** Ads ## Request Body **Content-Type:** `application/json` **Find active high-reach ads without a text search term:** ```json { "sortBy": "newest", "order": "desc", "status": "active", "platforms": [ "facebook" ], "minDaysRunning": 7, "reachPeriod": "last7d", "minReach": 10000, "limit": 25 } ``` **Top ads scaling over the last 7 days:** Use 7-day reach delta sorting for natural-language prompts such as “top ads leggings femme sur les 7 derniers jours”. This does not add first-seen date filters unless createdAfter or adsTimePeriod is supplied. ```json { "search": [ "leggings femme" ], "searchType": "adCopy", "keywordMode": "all", "sortBy": "reachDelta7d", "order": "desc", "reachPeriod": "last7d", "minReach": 1, "status": "active", "platforms": [ "facebook" ], "limit": 20 } ``` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `search` | `string`[] | No | Optional list of search terms used by the advanced ads query engine. | | `searchType` | `adCopy` \| `brand` \| `website` \| `domain` \| `urlContains` | No | Search mode for this request. Public camelCase values map to the same internal /ads fields: `adCopy` → `ad_copy`, `brand` → `brand`, `website` → `website_copy`, `domain` → `domain`, `urlContains` → `url_contains`. | | `keywordMode` | `any` \| `all` | No | How multiple search keywords are combined. Allowed values: `any`, `all`. | | `sortBy` | `createdAt` \| `longestRunning` \| `relevance` \| `relevanceScore` \| `newest` \| `mostDuplicates` \| `reach` \| `reachDelta1d` \| `reachDelta7d` \| `reachDelta30d` \| `rankDelta7d` \| `rankDelta14d` \| `rankDelta30d` \| `adOrder` | No | Sort key for this request. Allowed values: `createdAt`, `longestRunning`, `relevance`, `relevanceScore`, `newest`, `mostDuplicates`, `reach`, `reachDelta1d`, `reachDelta7d`, `reachDelta30d`, `adOrder`. | | `order` | `asc` \| `desc` | No | Sort direction for this request. Allowed values: `asc`, `desc`. | | `page` | `number` | No | | | `limit` | `number` | No | | | `platforms` | `facebook`[] | No | Accepted public v1 platform values. TikTok is not available in public v1. | | `mediaType` | `image` \| `video` \| `carousel` | No | Creative media type filter for this request. Allowed values: `image`, `video`, `carousel`. `carousel` maps to indexed carousel creatives and is not a DCO filter. | | `createdAfter` | `string` | No | | | `createdBefore` | `string` | No | | | `minFbPageCreationDate` | `string` | No | | | `maxFbPageCreationDate` | `string` | No | | | `minLastSeenDate` | `string` | No | | | `maxLastSeenDate` | `string` | No | | | `minDaysRunning` | `number` | No | | | `maxDaysRunning` | `number` | No | | | `status` | `active` \| `inactive` \| `all` | No | Status filter for this request. Allowed values: `active`, `inactive`, `all`. | | `minDuplicates` | `number` | No | | | `maxDuplicates` | `number` | No | | | `minDescriptionLength` | `number` | No | | | `maxDescriptionLength` | `number` | No | | | `minVideoDuration` | `number` | No | | | `maxVideoDuration` | `number` | No | | | `maxAdOrder` | `number` | No | | | `adRankMode` | `percentile` \| `rank` | No | Rank interpretation mode. Allowed values: `percentile`, `rank`. | | `adRankBasis` | `current` \| `alltime` | No | Rank basis used for ad rank filters. Allowed values: `current`, `alltime`. | | `maxAdRankValue` | `number` | No | | | `growthRank` | `object` | No | Advanced rank trend filter. Direction filters are ORed; period selects the rank-delta window when every rule uses the same supported window. minChange/unit are accepted for forward compatibility; use minRankDelta for an enforced absolute minimum rank improvement. | | `rankDeltaWindow` | `7d` \| `14d` \| `30d` | No | Rank-delta window used by growthRank/minRankDelta. Overrides the window inferred from growthRank.period. | | `minRankDelta` | `number` | No | Minimum absolute rank improvement for ad-rank mover filters. | | `adLanguage` | `string`[] | No | | | `cta` | `string`[] | No | | | `landingPages` | `string`[] | No | Landing page URL/domain filters. Mirrors the app ads table landingPages filter. | | `adCopyHashes` | `string`[] | No | Ad copy hash filters. Mirrors the app ads table adCopyHashes filter. | | `minReach` | `number` | No | Minimum reach threshold. Backed by the internal reach/impressions analytics fields. | | `maxReach` | `number` | No | Maximum reach threshold. Backed by the internal reach/impressions analytics fields. | | `minAge` | `number` | No | | | `maxAge` | `number` | No | | | `sex` | `men` \| `women` \| `all` | No | Audience gender filter. Allowed values: `men`, `women`, `all`. | | `adCountries` | `object` | No | Countries where the ad is distributed. Uses ISO 3166-1 alpha-2 country codes. | | `mainCountries` | `string`[] | No | Primary audience country filter, backed by Meta's EU/UK ad transparency reporting. Only EU/EEA, UK and French overseas codes exist in that data: US and other non-EU codes match nothing. Use adCountries for those markets. | | `spender` | `big-spender` \| `rising-star` \| `brandtracker` | No | Spender segment filter. Allowed values: `big-spender`, `rising-star`, `brandtracker`. | | `partners` | `boolean` | No | | | `partnerIds` | `string`[] | No | Partner badge ids to include. Mirrors the app ads table partnerIds filter. | | `minTraffic` | `number` | No | | | `maxTraffic` | `number` | No | | | `trafficGrowth` | `object` | No | Traffic growth filter. Uses OR groups (`anyOf`) made of AND-ed rules (`all`). Values are percentage thresholds. | | `minAds` | `number` | No | | | `maxAds` | `number` | No | | | `adsGrowth` | `object` | No | Ads growth filter. Uses OR groups (`anyOf`) made of AND-ed rules (`all`). Values are percentage thresholds. | | `pageReachGrowth` | `object` | No | Page reach growth filter. Uses OR groups (`anyOf`) made of AND-ed rules (`all`). | | `adReachGrowth` | `object` | No | Ad reach growth filter. Uses OR groups (`anyOf`) made of AND-ed rules (`all`). | | `categoryIds` | `number`[] | No | Google category facet ids matched against ads/shop google_categories. | | `minProducts` | `number` | No | | | `maxProducts` | `number` | No | | | `minBestSellerPrice` | `number` | No | | | `maxBestSellerPrice` | `number` | No | | | `themes` | `string`[] | No | | | `pixels` | `string`[] | No | | | `excludePixels` | `string`[] | No | | | `languages` | `string`[] | No | | | `currencies` | `string`[] | No | | | `shopifyApps` | `string`[] | No | Shopify app UUIDs returned by the Shopify Apps facets endpoint. | | `excludeShopifyApps` | `string`[] | No | Shopify app UUIDs to exclude. Values must not overlap shopifyApps. | | `adsTimePeriod` | `last24h` \| `last7d` \| `last30d` | No | Relative ad first-seen time window. When createdAfter is omitted, this is converted to an internal first-seen lower bound at the UTC day boundary for the selected period. It also selects the ads metric period used by minAds/maxAds. | | `minDate` | `string` | No | | | `maxDate` | `string` | No | | | `creationCountry` | `object` | No | Advertiser creation country filter using ISO 3166-1 alpha-2 country codes. | | `market` | `object` | No | Market filter grouped by primary markets, secondary markets, and excluded markets. | | `shopifyPlus` | `plus` \| `non-plus` \| `all` | No | Shopify Plus filter. Allowed values: `plus`, `non-plus`, `all`. | | `minTrustpilotScore` | `number` | No | Minimum Trustpilot score. | | `maxTrustpilotScore` | `number` | No | Maximum Trustpilot score. | | `minTrustpilotReviews` | `number` | No | Minimum Trustpilot review count. | | `maxTrustpilotReviews` | `number` | No | Maximum Trustpilot review count. | | `minSpend` | `number` | No | Minimum estimated spend. Uses cpm when provided, otherwise the public API default CPM of 9. | | `maxSpend` | `number` | No | Maximum estimated spend. Uses cpm when provided, otherwise the public API default CPM of 9. | | `cpm` | `number` | No | CPM in euros per 1,000 reach used for spend filters and estimatedSpend. Defaults to 9 when omitted. | | `spendPeriod` | `total` \| `last24h` \| `last7d` \| `last30d` | No | Metric period used by minSpend/maxSpend. By itself this parameter does not filter results. | | `reachPeriod` | `total` \| `last24h` \| `last7d` \| `last30d` | No | Metric period used by minReach/maxReach. Reach is the public Meta Ad Library vocabulary for impressions where available. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | `number` | No | Minimum estimated spend per page. Uses cpm when provided, otherwise the public API default CPM of 9. | | `maxSpendPerPage` | `number` | No | Maximum estimated spend per page. Uses cpm when provided, otherwise the public API default CPM of 9. | | `spendPerPagePeriod` | `total` \| `last24h` \| `last7d` \| `last30d` | No | Metric period used by minSpendPerPage/maxSpendPerPage. By itself this parameter does not filter results. | | `minFacebookLikes` | `number` | No | | | `maxFacebookLikes` | `number` | No | | | `minInstagramFollowers` | `number` | No | | | `maxInstagramFollowers` | `number` | No | | | `minReachPerPage` | `number` | No | Minimum page reach threshold. Backed by the internal page impressions fields. | | `maxReachPerPage` | `number` | No | Maximum page reach threshold. Backed by the internal page impressions fields. | | `reachPerPagePeriod` | `total` \| `last24h` \| `last7d` \| `last30d` | No | Metric period used by minReachPerPage/maxReachPerPage. Reach is the public Meta Ad Library vocabulary for page impressions where available. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `technologies` | `checkoutchamp` \| `clickfunnels` \| `funnelish` \| `gempages` \| `magento` \| `odoo` \| `pagefly` \| `prestashop` \| `shopify` \| `shoplazza` \| `shopline` \| `squarespace` \| `wheelio` \| `wix` \| `woocommerce` \| `wordpress` \| `zipify-pages`[] | No | Technology slugs supported by the current ads index. Supported values: checkoutchamp, clickfunnels, funnelish, gempages, magento, odoo, pagefly, prestashop, shopify, shoplazza, shopline, squarespace, wheelio, wix, woocommerce, wordpress, zipify-pages. | | `hideLowReach` | `boolean` | No | Exclude low reach ads. Backed by the internal low impressions flag. | | `hideNonEuUkAds` | `boolean` | No | | | `hideSavedAds` | `boolean` | No | | | `hideDecliningRankAds` | `boolean` | No | | | `trackedPages` | `string`[] | No | | | `maxAdsPerBrand` | `number` | No | | **`growthRank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | Structured rank trend request shape. Current filtering ORs all provided directions and ignores grouping, period, minChange, and unit. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`adCountries` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `include` | `string`[] | No | ISO 3166-1 alpha-2 country codes to include. | | `exclude` | `string`[] | No | ISO 3166-1 alpha-2 country codes to exclude. | **`trafficGrowth` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | OR groups of traffic growth rules. Each group combines its rules with AND. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`adsGrowth` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | OR groups of ads growth rules. Each group combines its rules with AND. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`pageReachGrowth` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | OR groups of reach growth rules. Each group combines its rules with AND. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`adReachGrowth` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `anyOf` | `object`[] | Yes | OR groups of reach growth rules. Each group combines its rules with AND. | **`anyOf[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `all` | `object`[] | Yes | | **`all[]` item properties:** **`creationCountry` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `include` | `string`[] | No | ISO 3166-1 alpha-2 country codes to include. | | `exclude` | `string`[] | No | ISO 3166-1 alpha-2 country codes to exclude. | **`market` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `main` | `string`[] | No | Countries that must match the primary market. | | `among` | `string`[] | No | Countries that can appear among the ad markets. | | `exclude` | `string`[] | No | Countries to exclude from the ad markets. | ## Responses ### 200 - Paginated advanced ads query response using the public ads contract. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#list-landing-pages # List landing pages `GET /v1/ads/facets/landing-pages` Aggregates distinct normalized landing-page URLs for Meta pages or one shop domain. Charges one credit per distinct URL returned and never returns ad rows. **Tags:** Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scopeTrackedPages` | query | No | `string`[] | Repeated or comma-separated Meta/Facebook page identifiers. Mutually exclusive with scopeDomain. | | `scopeDomain` | query | No | `string` | Shop URL or hostname. Mutually exclusive with scopeTrackedPages. | | `status` | query | No | `active` \| `inactive` \| `all` | | | `limit` | query | No | `integer` | | ## Responses ### 200 - Landing-page URL counts, active-ad counts, scope metadata, and truncation state. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `url` | `string` | Yes | Normalized landing-page URL in lowercase, without query parameters or trailing slashes. | | `usageCount` | `number` | Yes | Number of matching ads using this landing-page URL. | | `activeAdsCount` | `number` | Yes | Number of matching active ads using this landing-page URL. | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scopeType` | `trackedPages` \| `domain` | Yes | | | `scopeValueCount` | `number` | Yes | | | `status` | `active` \| `inactive` \| `all` | Yes | | | `limit` | `number` | Yes | | | `isTruncated` | `boolean` | Yes | True when more normalized domains matched than the response limit or Elasticsearch omitted buckets. | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#create-or-return-an-ad-share-url # Create or return an ad share URL `POST /v1/ads/{adId}/share` Creates or returns the existing Trendtrack public webapp share URL for an ad. This is classified as a workspace-scoped write because it creates share state server-side when needed; delegated OAuth/API-key callers must be workspace writers. **Tags:** Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `adId` | path | Yes | `string` | Trendtrack ad identifier returned as `adId` by the Public API. | ## Responses ### 200 - Public ad share URL response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adId` | `string` | Yes | Trendtrack ad identifier returned as `adId` by the Public API. | | `id` | `string` | Yes | Identifier of the share_ads row used by the webapp share page. | | `slug` | `string` | Yes | Human-readable share slug when available. | | `shareUrl` | `string` | Yes | Fully qualified Trendtrack webapp URL for this public share. | | `sharePath` | `string` | Yes | Webapp-relative path for this public share. | | `createdAt` | `string` | Yes | | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#delete-an-ad-share-url # Delete an ad share URL `DELETE /v1/ads/{adId}/share` **Tags:** Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `adId` | path | Yes | `string` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adId` | `string` | Yes | | | `deleted` | `boolean` | Yes | | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#get-an-ad-media-url # Get an ad media URL `GET /v1/ads/{adId}/media-url` Returns URL metadata for the best available media asset for an ad. This endpoint does not proxy or download the binary media. **Tags:** Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `adId` | path | Yes | `string` | Trendtrack ad identifier returned as `adId` by the Public API. | ## Responses ### 200 - Public ad media URL response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adId` | `string` | Yes | Trendtrack ad identifier returned as `adId` by the Public API. | | `mediaType` | `image` \| `video` \| `carousel` \| `unknown` | Yes | | | `url` | `string` | Yes | Best available media URL for this ad. This endpoint returns metadata only and does not proxy the binary asset. | | `urlType` | `public_asset` \| `external_direct` | Yes | public_asset is a stable Trendtrack/public URL. external_direct may expire or be subject to upstream access controls. | | `selectedSource` | `media_url` \| `thumbnail_url` | Yes | Source column selected for url. | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `filename` | `string` | Yes | Suggested filename derived from the ad id and selected URL. | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#get-an-ad-by-id # Get an ad by id `GET /v1/ads/{adId}` Returns a single public ad detail object by ad id. The current backing identifier is the internal composite ad id, but the public contract exposes it as id. **Tags:** Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `adId` | path | Yes | `string` | Trendtrack ad identifier returned as `adId` by the Public API. | ## Responses ### 200 - Public ad detail response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | | `transcript` | `object` | Yes | | | `creativeAnalysis` | `object` | Yes | | | `links` | `object` | Yes | | | `shops` | `object`[] | Yes | | | `pageAnalytics` | `object` | Yes | | | `resolvedFrom` | `object` | No | Present only when the served ad is not the requested one: `id` is then the ad Trendtrack serves for the requested ad's duplicate group. | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`transcript` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `language` | `string` | Yes | | | `languageConfidence` | `number` | Yes | | | `segments` | `object`[] | Yes | | | `fullText` | `string` | Yes | | **`segments[]` item properties:** **`creativeAnalysis` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `hook` | `object` | Yes | | **`hook` properties:** **`links` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adLibraryUrl` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | **`shops[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shopId` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `isPrimary` | `boolean` | Yes | | | `traffic` | `number` | Yes | | | `categories` | `string`[] | Yes | | **`pageAnalytics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `impressionsHistory` | `object`[] | Yes | Historical Facebook page impressions when available; ad-level DTOs may expose comparable Meta Ad Library vocabulary as reach. | | `facebookLikesHistory` | `object`[] | Yes | | | `instagramFollowersHistory` | `object`[] | Yes | | **`impressionsHistory[]` item properties:** **`facebookLikesHistory[]` item properties:** **`instagramFollowersHistory[]` item properties:** **`resolvedFrom` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedId` | `string` | Yes | The ad id that was requested. | | `reason` | `duplicate_group` | Yes | duplicate_group: the requested ad is a duplicate of the served ad (same collationId); the served ad carries the group's figures. | --- Tag: Ads · Reference: https://docs.trendtrack.io/docs/reference/api/ads#get-ad-reach-history # Get ad reach history `GET /v1/ads/{adId}/reach-history` Returns the public daily reach history for one ad. The series is intentionally lightweight and keeps reach as the canonical metric term. **Tags:** Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `adId` | path | Yes | `string` | Trendtrack ad identifier returned as `adId` by the Public API. | | `limit` | query | No | `integer` | | ## Responses ### 200 - Public ad reach history response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `reach` | `number` | Yes | Daily ad reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | --- Tag: Google Ads · Reference: https://docs.trendtrack.io/docs/reference/api/google-ads#query-google-ads # Query Google Ads `POST /v1/google-ads/query` Queries the dedicated Google Ads library. Networks, audience countries, and Google category ids map to verified google-ads-search fields. **Tags:** Google Ads ## Request Body **Content-Type:** `application/json` **US Shopping ads in Women’s Clothing:** ```json { "status": "active", "networks": [ "shopping" ], "categoryIds": [ 24 ], "audienceCountries": { "include": [ "US" ] }, "sortBy": "newest", "order": "desc", "page": 1, "limit": 25 } ``` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `search` | `string`[] | No | Optional Google advertiser/domain search terms. | | `status` | `active` \| `inactive` \| `all` | No | | | `networks` | `search` \| `shopping` \| `maps` \| `youtube` \| `other`[] | No | Google delivery networks. Values are normalized to the casing used by the Google Ads search index. | | `categoryIds` | `number`[] | No | Google category ids returned by GET /v1/google-ads/facets/categories. These correspond to the app legacy niches parameter. | | `audienceCountries` | `object` | No | Audience-country filter. This is intentionally distinct from advertiser/shop creation country. | | `publishedAfter` | `string` | No | | | `publishedBefore` | `string` | No | | | `minDaysRunning` | `number` | No | | | `maxDaysRunning` | `number` | No | | | `minReach` | `number` | No | | | `maxReach` | `number` | No | | | `sortBy` | `newest` \| `reach` \| `longestRunning` | No | | | `order` | `asc` \| `desc` | No | | | `page` | `object` | No | | | `limit` | `object` | No | | **`audienceCountries` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `include` | `string`[] | No | ISO 3166-1 alpha-2 audience countries to include. Google Ads matches targeting.main_country. | | `exclude` | `string`[] | No | ISO 3166-1 alpha-2 audience countries to exclude. Google Ads matches targeting.main_country. | ## Responses ### 200 - Paginated Google Ads response. One returned ad is one billable ads credit. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `googleAdId` | `string` | Yes | | | `status` | `active` \| `inactive` | Yes | | | `network` | `search` \| `shopping` \| `maps` \| `youtube` \| `other` | Yes | | | `firstSeenAt` | `string` | Yes | | | `lastSeenAt` | `string` | Yes | | | `daysRunning` | `number` | Yes | | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `reach` | `object` | Yes | | | `audience` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` | Yes | | | `url` | `string` | Yes | | | `format` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `shopName` | `string` | Yes | | | `domain` | `string` | Yes | | | `websiteId` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `liveAds` | `object` | Yes | | **`liveAds` properties:** **`reach` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `value` | `number` | Yes | | | `lowerBound` | `number` | Yes | | | `upperBound` | `number` | Yes | | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `mainCountry` | `string` | Yes | | | `countries` | `object`[] | Yes | | | `remarketing` | `boolean` | Yes | | | `interest` | `boolean` | Yes | | **`countries[]` item properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Google Ads · Reference: https://docs.trendtrack.io/docs/reference/api/google-ads#list-google-ads-network-facets # List Google Ads network facets `GET /v1/google-ads/facets/networks` Returns the normalized Google delivery networks accepted by POST /v1/google-ads/query. **Tags:** Google Ads ## Responses ### 200 - Google delivery networks with live ad counts. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `value` | `string` | Yes | | | `label` | `string` | Yes | | | `adsCount` | `number` | Yes | | --- Tag: Google Ads · Reference: https://docs.trendtrack.io/docs/reference/api/google-ads#list-google-ads-audience-country-facets # List Google Ads audience-country facets `GET /v1/google-ads/facets/countries` Returns audience country codes observed in the Google Ads search index. **Tags:** Google Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | | | `limit` | query | No | `object` | | | `offset` | query | No | `object` | | ## Responses ### 200 - Google audience countries with live ad counts. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `value` | `string` | Yes | | | `label` | `string` | Yes | | | `adsCount` | `number` | Yes | | --- Tag: Google Ads · Reference: https://docs.trendtrack.io/docs/reference/api/google-ads#list-google-ads-category-facets # List Google Ads category facets `GET /v1/google-ads/facets/categories` Returns the Google category ids accepted by categoryIds on POST /v1/google-ads/query. **Tags:** Google Ads ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | | | `limit` | query | No | `object` | | | `offset` | query | No | `object` | | ## Responses ### 200 - Paginated Google categories with advertiser usage counts. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `path` | `string` | Yes | | | `parentId` | `number` | Yes | | | `advertiserUsageCount` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#list-shops # List shops `GET /v1/shops` Returns the lightweight public shops browse surface. This endpoint stays intentionally simple and covers the default discovery path through search, pagination, sorting, and a small stable subset of filters. For the full advanced filtering contract, use POST /v1/shops/query. **Tags:** Shops ## Parameters **Query parameter groups:** - Pagination: `offset`, `limit` - Search: `search` - Time and snapshots: `adsTimePeriod`, `createdAfter`, `createdBefore` - Sorting: `sortBy`, `order` - Filters: `minMonthlyVisits`, `maxMonthlyVisits`, `minActiveAds`, `maxActiveAds`, `hasTikTok`, `minTikTokFollowers`, `maxTikTokFollowers`, `minTikTokActiveAds`, `maxTikTokActiveAds`, `minTikTokTotalPosts`, `maxTikTokTotalPosts`, `minProductsCount`, `maxProductsCount`, `isShopifyPlus`, `categoryIds`, `pixelIds`, `excludePixelIds`, `shopifyAppIds`, `excludeShopifyAppIds`, `languages`, `currencies`, `minTrustpilotRating`, `maxTrustpilotRating`, `minTrustpilotReviewCount`, `maxTrustpilotReviewCount`, `minMonthlySales`, `maxMonthlySales`, `minUnitsSold`, `maxUnitsSold` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | Optional broad shop identity search term matched against domain, related domains, and shop name. This GET browse search remains broad; use POST /v1/shops/query with searchType="domain" for exact domain matching. | | `sortBy` | query | No | `monthlyVisits` \| `activeAds` \| `growth30d` \| `productsCount` \| `createdAt` \| `tiktokFollowers` \| `tiktokActiveAds` \| `tiktokTotalPosts` \| `tiktokAvgActiveAds7d` \| `tiktokAvgActiveAds30d` \| `estMonthlySales` \| `unitsSold` | Optional sort key for the shops list. Defaults to monthlyVisits. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `offset` | query | No | `integer` | Pagination offset. Defaults to 0. | | `limit` | query | No | `integer` | Maximum number of shops to return. Defaults to 32. | | `minMonthlyVisits` | query | No | `integer` | Optional minimum monthly visits filter. | | `maxMonthlyVisits` | query | No | `integer` | Optional maximum monthly visits filter. | | `minActiveAds` | query | No | `number` | Optional minimum active ads filter. The metric follows adsTimePeriod. | | `maxActiveAds` | query | No | `number` | Optional maximum active ads filter. The metric follows adsTimePeriod. | | `adsTimePeriod` | query | No | `last24h` \| `last7d` \| `last30d` | Optional time period used by active ads filters and sorting. Defaults to last24h. | | `hasTikTok` | query | No | `boolean` | Optional TikTok presence filter backed by the legacy flat shop index. true requires an indexed TikTok page or handle; false excludes shops with one. | | `minTikTokFollowers` | query | No | `number` | | | `maxTikTokFollowers` | query | No | `number` | | | `minTikTokActiveAds` | query | No | `number` | | | `maxTikTokActiveAds` | query | No | `number` | | | `minTikTokTotalPosts` | query | No | `number` | | | `maxTikTokTotalPosts` | query | No | `number` | | | `minProductsCount` | query | No | `integer` | Optional minimum products count filter. | | `maxProductsCount` | query | No | `integer` | Optional maximum products count filter. | | `createdAfter` | query | No | `string` | Optional inclusive lower bound for shop creation date. | | `createdBefore` | query | No | `string` | Optional inclusive upper bound for shop creation date. | | `isShopifyPlus` | query | No | `boolean` | Optional Shopify Plus filter. | | `categoryIds` | query | No | `integer`[] | Optional category ids. Uses the same index field as POST /v1/shops/query categoryIds. | | `pixelIds` | query | No | `string`[] | Optional canonical pixel UUIDs. Uses the same index fields as POST /v1/shops/query pixelIds. Resolve display names through /v1/facets/pixels. | | `excludePixelIds` | query | No | `string`[] | Optional canonical pixel UUIDs to exclude. Uses the same index fields as POST /v1/shops/query excludePixelIds. | | `shopifyAppIds` | query | No | `string`[] | Optional canonical Shopify app UUIDs. Uses the same index field as POST /v1/shops/query shopifyAppIds. | | `excludeShopifyAppIds` | query | No | `string`[] | Optional canonical Shopify app UUIDs to exclude. Uses the same index field as POST /v1/shops/query excludeShopifyAppIds. | | `languages` | query | No | `string`[] | Optional default language filters. Accepts repeated query params or a comma-separated list. | | `currencies` | query | No | `string`[] | Optional default currency filters. Accepts repeated query params or a comma-separated list. | | `minTrustpilotRating` | query | No | `number` | Optional minimum Trustpilot rating filter. | | `maxTrustpilotRating` | query | No | `number` | Optional maximum Trustpilot rating filter. | | `minTrustpilotReviewCount` | query | No | `integer` | Optional minimum Trustpilot reviews filter. | | `maxTrustpilotReviewCount` | query | No | `integer` | Optional maximum Trustpilot reviews filter. | | `minMonthlySales` | query | No | `integer` | Minimum estimated revenue over the last 30 days, in USD (sales tracker). Shops the tracker does not follow are excluded. | | `maxMonthlySales` | query | No | `integer` | Maximum estimated revenue over the last 30 days, in USD (sales tracker). | | `minUnitsSold` | query | No | `integer` | Minimum units sold over the last 30 days (sales tracker). Shops the tracker does not follow are excluded. | | `maxUnitsSold` | query | No | `integer` | Maximum units sold over the last 30 days (sales tracker). | ## Responses ### 200 - Paginated shops response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `isShopifyPlus` | `boolean` | Yes | | **`catalog` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `productsCount` | `number` | Yes | | | `mainCategory` | `string` | Yes | | | `bestSellers` | `object`[] | Yes | Top best-selling products for this shop. Capped at 3 items. Sourced from `shopify_best_selling` when available, with fallback to `best_sellers_object` then `best_sellers` image URLs. | **`bestSellers[]` item properties:** **`traffic` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `monthlyVisits` | `number` | Yes | | | `growth30d` | `number` | Yes | | | `history` | `object`[] | Yes | Monthly visits time-series, sorted ascending by period. Capped at the 6 most recent months. | | `topCountries` | `object`[] | Yes | Top markets by traffic share (country code + share in [0, 1]). Derived from SimilarWeb geography breakdown when available, otherwise from the `countries` list with null shares. | **`history[]` item properties:** **`topCountries[]` item properties:** **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currency` | `USD` | Yes | The tracker converts every product price to USD. | | `estMonthlySales` | `number` | Yes | Estimated revenue over the last 30 days, in whole USD. An estimate from the sales tracker; 0 means the tracker measured no sales. | | `unitsSold` | `number` | Yes | Units sold over the same 30 days. A floor: the shop sold at least this many. | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `totalAds` | `number` | No | Total Meta ads (active and inactive), as displayed on the SaaS shop card. Included in similar-shops and image-search shop summaries; null when unknown. Not a TikTok or cross-platform total. | | `activeAds` | `number` | Yes | | | `linkedAdvertisersCount` | `number` | Yes | | | `history` | `object`[] | Yes | Weekly active-ads time-series, sorted ascending by period. Capped at the 26 most recent weekly points (~6 months). | | `topCountries` | `object`[] | Yes | Top countries by Meta ads volume (share in [0, 1]). Derived from the shop-level `ads_country_stats` aggregate across all linked advertisers. | **`history[]` item properties:** **`topCountries[]` item properties:** **`tiktok` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `hasTikTok` | `boolean` | Yes | True when the shop has an indexed TikTok page/handle or TikTok rollup activity. This is independent from Meta advertising fields. | | `pageId` | `string` | Yes | | | `handle` | `string` | Yes | | | `profileMetrics` | `object` | Yes | | | `activity` | `object` | Yes | | | `lastUpdatedAt` | `string` | Yes | | **`profileMetrics` properties:** **`activity` properties:** **`googleAds` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `status` | `available` \| `unavailable` | Yes | available when the Google Ads aggregation succeeded; unavailable when enrichment failed or was intentionally skipped. Shop search still succeeds when unavailable. | | `liveAds` | `number` | Yes | | | `adsLaunched30d` | `number` | Yes | Google Ads first seen in the most recent 30 days. | | `reach` | `object` | Yes | | | `topCountries` | `object`[] | Yes | Top Google Ads audience countries. Distinct from shop.profile.countryCode and traffic.topCountries. | | `platformMix` | `object`[] | Yes | | **`reach` properties:** **`topCountries[]` item properties:** **`platformMix[]` item properties:** **`latestAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `mediaType` | `image` \| `video` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#query-shops # Query shops `POST /v1/shops/query` Returns the advanced public shops discovery surface. This endpoint is the canonical public route for complex filtering and sorting, while keeping the response aligned with the standard public ShopSummary contract. searchType=domain performs exact domain/related-domain matching from a domain or URL and does not fall back to broad wildcard/text matching. **Tags:** Shops ## Request Body **Content-Type:** `application/json` **Find one shop by exact domain or URL (domain/related-domain exact matching):** ```json { "search": "https://www.allbirds.com/products", "searchType": "domain", "limit": 10, "offset": 0 } ``` **Find growing shops by product text in the US market:** ```json { "search": "pet products", "searchType": "productName", "sortBy": "monthlyVisits", "order": "desc", "adsTimePeriod": "last7d", "minActiveAds": 10, "minMonthlyVisits": 5000, "mainMarketCountries": [ "US" ], "limit": 25, "offset": 0 } ``` **Find shops with broad website text search:** ```json { "search": "organic cotton", "searchType": "shopContains", "limit": 25, "offset": 0 } ``` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `search` | `string` | No | Optional search string. For searchType="domain", send a domain or URL for exact domain/related-domain matching. For broad website text search, use shopContains. For product text, use productName. Do not send unsupported legacy keys name, domain, or domains. | | `searchType` | `domain` \| `productName` \| `shopContains` | No | Search mode. domain performs exact domain/related-domain matching from a domain or URL, productName searches indexed product text, and shopContains matches website text, keeping the 10,000 most relevant shops before filters and sorting are applied. | | `sortBy` | `relevance` \| `monthlyVisits` \| `activeAds` \| `growth30d` \| `productsCount` \| `createdAt` \| `tiktokFollowers` \| `tiktokActiveAds` \| `tiktokTotalPosts` \| `tiktokAvgActiveAds7d` \| `tiktokAvgActiveAds30d` \| `estMonthlySales` \| `unitsSold` | No | Sort key for the advanced shops query surface. relevance orders by monthlyVisits, as in the Trendtrack app: the search text filters shops but does not rank them. | | `order` | `asc` \| `desc` | No | Enum value accepted by this request. Allowed values: `asc`, `desc`. | | `offset` | `number` | No | | | `limit` | `number` | No | | | `categoryIds` | `number`[] | No | Optional category ids used by the current shop discovery index. | | `minEstimatedRevenue` | `number` | No | Deprecated and rejected with 400: use minMonthlySales, read from the sales tracker. | | `maxEstimatedRevenue` | `number` | No | Deprecated and rejected with 400: use maxMonthlySales, read from the sales tracker. | | `minMonthlySales` | `number` | No | Minimum estimated revenue over the last 30 days, in USD (sales tracker). Shops the tracker does not follow are excluded. | | `maxMonthlySales` | `number` | No | Maximum estimated revenue over the last 30 days, in USD (sales tracker). | | `minUnitsSold` | `number` | No | Minimum units sold over the last 30 days (sales tracker). Shops the tracker does not follow are excluded. | | `maxUnitsSold` | `number` | No | Maximum units sold over the last 30 days (sales tracker). | | `minMonthlyVisits` | `number` | No | | | `maxMonthlyVisits` | `number` | No | | | `minProductsCount` | `number` | No | | | `maxProductsCount` | `number` | No | | | `createdAfter` | `string` | No | | | `createdBefore` | `string` | No | | | `mainMarketCountries` | `string`[] | No | Optional main audience-market filter using uppercase ISO 3166-1 alpha-2 country codes matched against the indexed main_market field. | | `marketCountries` | `string`[] | No | Optional audience-market filter for shops where these countries appear among the indexed traffic markets. | | `excludeMarketCountries` | `string`[] | No | | | `minBestSellerPrice` | `number` | No | | | `maxBestSellerPrice` | `number` | No | | | `minActiveAds` | `number` | No | Optional minimum active ads filter. The metric follows adsTimePeriod. | | `maxActiveAds` | `number` | No | Optional maximum active ads filter. The metric follows adsTimePeriod. | | `adsTimePeriod` | `last24h` \| `last7d` \| `last30d` | No | Time window accepted by this request. Allowed values: `last24h`, `last7d`, `last30d`. | | `hasTikTok` | `boolean` | No | Optional TikTok presence filter backed by the legacy flat shop index. true requires an indexed TikTok page or handle; false excludes shops with one. | | `minTikTokFollowers` | `number` | No | | | `maxTikTokFollowers` | `number` | No | | | `minTikTokActiveAds` | `number` | No | | | `maxTikTokActiveAds` | `number` | No | | | `minTikTokTotalPosts` | `number` | No | | | `maxTikTokTotalPosts` | `number` | No | | | `isShopifyPlus` | `boolean` | No | | | `trafficGrowth` | `object`[] | No | Traffic growth filters. Each condition uses `period`, `comparison`, and `value`; optional `operator` links the condition to the next one. | | `adsGrowth` | `object`[] | No | Ads growth filters. Each condition uses `period`, `comparison`, and `value`; optional `operator` links the condition to the next one. | | `pageReachGrowth` | `object`[] | No | Page reach growth filters. Each condition uses `period`, `comparison`, and `value`; optional `operator` links the condition to the next one. | | `adReachGrowth` | `object`[] | No | Ad reach growth filters. Each condition uses `period`, `comparison`, and `value`; optional `operator` links the condition to the next one. | | `creationCountries` | `string`[] | No | | | `excludeCreationCountries` | `string`[] | No | | | `displayInTrending` | `boolean` | No | When true, restricts results to shops visible in the Trendtrack trending shops feed. | | `themeIds` | `string`[] | No | Optional canonical Shopify theme UUIDs backed by the current website discovery index. Use /v1/facets/themes to resolve display names. | | `pixelIds` | `string`[] | No | Optional canonical pixel UUIDs backed by the current website discovery index. Use /v1/facets/pixels to resolve display names. | | `excludePixelIds` | `string`[] | No | Optional canonical pixel UUIDs to exclude. Use /v1/facets/pixels to resolve display names. | | `shopifyAppIds` | `string`[] | No | Optional canonical Shopify app UUIDs backed by the current website discovery index. Use /v1/facets/shopify-apps to resolve names to ids. | | `excludeShopifyAppIds` | `string`[] | No | Optional canonical Shopify app UUIDs to exclude. Use /v1/facets/shopify-apps to resolve names to ids. | | `minTrustpilotRating` | `number` | No | | | `maxTrustpilotRating` | `number` | No | | | `minTrustpilotReviewCount` | `number` | No | | | `maxTrustpilotReviewCount` | `number` | No | | | `languages` | `string`[] | No | | | `currencies` | `string`[] | No | | | `dtcRegion` | `all` \| `us` \| `eu` | No | Optional DTC preset. all means any indexed DTC shop, while us and eu also apply the corresponding creation-country subset used by the app. | **`trafficGrowth[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `period` | `last30d` \| `last90d` \| `last180d` | Yes | Indexed traffic growth window. | | `value` | `number` | No | Minimum or maximum growth threshold, expressed as a percentage. | | `comparison` | `greater` \| `lower` | Yes | Comparison applied to the growth threshold. Use `greater` for gte and `lower` for lte semantics. | | `operator` | `and` \| `or` | No | Logical operator linking this condition to the next one in the array. | **`adsGrowth[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `period` | `last7d` \| `last30d` \| `last90d` | Yes | Indexed ads growth window. | | `value` | `number` | No | Minimum or maximum growth threshold, expressed as a percentage. | | `comparison` | `greater` \| `lower` | Yes | Comparison applied to the growth threshold. Use `greater` for gte and `lower` for lte semantics. | | `operator` | `and` \| `or` | No | Comparison operator for this rule. Allowed values: `and`, `or`. | **`pageReachGrowth[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `period` | `last7d` \| `last14d` \| `last30d` \| `last60d` \| `last90d` | Yes | Indexed reach growth window. | | `value` | `number` | No | Minimum or maximum growth threshold, expressed as a percentage. | | `comparison` | `greater` \| `lower` | Yes | Comparison applied to the growth threshold. Use `greater` for gte and `lower` for lte semantics. | | `operator` | `and` \| `or` | No | Comparison operator for this rule. Allowed values: `and`, `or`. | **`adReachGrowth[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `period` | `last7d` \| `last14d` \| `last30d` \| `last60d` \| `last90d` | Yes | Indexed reach growth window. | | `value` | `number` | No | Minimum or maximum growth threshold, expressed as a percentage. | | `comparison` | `greater` \| `lower` | Yes | Comparison applied to the growth threshold. Use `greater` for gte and `lower` for lte semantics. | | `operator` | `and` \| `or` | No | Comparison operator for this rule. Allowed values: `and`, `or`. | ## Responses ### 200 - Paginated advanced shops query response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `isShopifyPlus` | `boolean` | Yes | | **`catalog` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `productsCount` | `number` | Yes | | | `mainCategory` | `string` | Yes | | | `bestSellers` | `object`[] | Yes | Top best-selling products for this shop. Capped at 3 items. Sourced from `shopify_best_selling` when available, with fallback to `best_sellers_object` then `best_sellers` image URLs. | **`bestSellers[]` item properties:** **`traffic` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `monthlyVisits` | `number` | Yes | | | `growth30d` | `number` | Yes | | | `history` | `object`[] | Yes | Monthly visits time-series, sorted ascending by period. Capped at the 6 most recent months. | | `topCountries` | `object`[] | Yes | Top markets by traffic share (country code + share in [0, 1]). Derived from SimilarWeb geography breakdown when available, otherwise from the `countries` list with null shares. | **`history[]` item properties:** **`topCountries[]` item properties:** **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currency` | `USD` | Yes | The tracker converts every product price to USD. | | `estMonthlySales` | `number` | Yes | Estimated revenue over the last 30 days, in whole USD. An estimate from the sales tracker; 0 means the tracker measured no sales. | | `unitsSold` | `number` | Yes | Units sold over the same 30 days. A floor: the shop sold at least this many. | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `totalAds` | `number` | No | Total Meta ads (active and inactive), as displayed on the SaaS shop card. Included in similar-shops and image-search shop summaries; null when unknown. Not a TikTok or cross-platform total. | | `activeAds` | `number` | Yes | | | `linkedAdvertisersCount` | `number` | Yes | | | `history` | `object`[] | Yes | Weekly active-ads time-series, sorted ascending by period. Capped at the 26 most recent weekly points (~6 months). | | `topCountries` | `object`[] | Yes | Top countries by Meta ads volume (share in [0, 1]). Derived from the shop-level `ads_country_stats` aggregate across all linked advertisers. | **`history[]` item properties:** **`topCountries[]` item properties:** **`tiktok` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `hasTikTok` | `boolean` | Yes | True when the shop has an indexed TikTok page/handle or TikTok rollup activity. This is independent from Meta advertising fields. | | `pageId` | `string` | Yes | | | `handle` | `string` | Yes | | | `profileMetrics` | `object` | Yes | | | `activity` | `object` | Yes | | | `lastUpdatedAt` | `string` | Yes | | **`profileMetrics` properties:** **`activity` properties:** **`googleAds` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `status` | `available` \| `unavailable` | Yes | available when the Google Ads aggregation succeeded; unavailable when enrichment failed or was intentionally skipped. Shop search still succeeds when unavailable. | | `liveAds` | `number` | Yes | | | `adsLaunched30d` | `number` | Yes | Google Ads first seen in the most recent 30 days. | | `reach` | `object` | Yes | | | `topCountries` | `object`[] | Yes | Top Google Ads audience countries. Distinct from shop.profile.countryCode and traffic.topCountries. | | `platformMix` | `object`[] | Yes | | **`reach` properties:** **`topCountries[]` item properties:** **`platformMix[]` item properties:** **`latestAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `mediaType` | `image` \| `video` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#list-shops-similar-to-a-domain-or-shop-id # List shops similar to a domain or shop id `GET /v1/shops/{identifier}/similar` Returns a paginated list of similar shops using the public hybrid shops contract. The identifier can be a canonical domain or a public shop id / website UUID. When the resolved shop is not present in the similar shops engine, the endpoint still returns 200 with an empty data array and meta.shopExists=false. **Tags:** Shops ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `identifier` | path | Yes | `string` | Canonical shop domain or stable public shop id / website UUID used to resolve similar shops. | | `sortBy` | query | No | `relevance` \| `monthlyVisits` \| `activeAds` \| `growth30d` \| `productsCount` \| `createdAt` | Sort key for similar shops. createdAt uses request-time normalization while the backing creation_date field remains keyword-mapped; native date sorting requires an Elasticsearch mapping/reindex update. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `offset` | query | No | `integer` | Pagination offset. Defaults to 0. | | `limit` | query | No | `integer` | Maximum number of similar shops to return. Defaults to 32. | ## Responses ### 200 - Paginated similar shops response for the requested identifier. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shop` | `object` | Yes | | | `similarityScore` | `number` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** **`catalog` properties:** **`traffic` properties:** **`sales` properties:** **`advertising` properties:** **`tiktok` properties:** **`googleAds` properties:** **`latestAds[]` item properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shopExists` | `boolean` | Yes | False when the resolved shop/domain does not exist in the similar shops engine. | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#search-products-by-image # Search products by image `POST /v1/products/image-search` Finds the store products that look like an image, most similar first, one per shop by default (maxPerShop) and with the storefronts of one brand counted as one shop (groupBrands). Send the image as a multipart file or as a public URL; read the next pages with the returned searchId. Costs 4 credits per product returned. **Tags:** Shops ## Request Body **Content-Type:** `multipart/form-data` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `image` | `string` | No | Image file (JPEG, PNG or WEBP, 10 MB max), sent as multipart/form-data. Provide exactly one of image, imageUrl or searchId. | | `imageUrl` | `string` | No | Public http(s) URL of the image. The server downloads it (10 MB max). | | `searchId` | `string` | No | searchId returned by a previous image search of this workspace. Replays the same image to read its next pages without sending it again. | | `offset` | `number` | No | | | `limit` | `number` | No | | | `groupBrands` | `boolean` | No | Count the storefronts of one brand (same root domain across countries, or the same Shopify store on several domains) as one shop. False keeps every storefront apart; the same store on several domains always counts once. | | `maxPerShop` | `number` | No | Products returned per shop (or brand), most similar first; 0 = no cap. A product repeated in one shop (variants, duplicate photos) is always returned once. | **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `image` | `string` | No | Image file (JPEG, PNG or WEBP, 10 MB max), sent as multipart/form-data. Provide exactly one of image, imageUrl or searchId. | | `imageUrl` | `string` | No | Public http(s) URL of the image. The server downloads it (10 MB max). | | `searchId` | `string` | No | searchId returned by a previous image search of this workspace. Replays the same image to read its next pages without sending it again. | | `offset` | `number` | No | | | `limit` | `number` | No | | | `groupBrands` | `boolean` | No | Count the storefronts of one brand (same root domain across countries, or the same Shopify store on several domains) as one shop. False keeps every storefront apart; the same store on several domains always counts once. | | `maxPerShop` | `number` | No | Products returned per shop (or brand), most similar first; 0 = no cap. A product repeated in one shop (variants, duplicate photos) is always returned once. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `product` | `object` | Yes | | | `shop` | `object` | Yes | | **`product` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shopifyId` | `number` | Yes | | | `title` | `string` | Yes | | | `imageUrl` | `string` | Yes | | | `price` | `number` | Yes | | | `currency` | `string` | Yes | | | `similarityScore` | `number` | Yes | Cosine similarity between the query image and the product image (0.7 to 1). | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** **`catalog` properties:** **`traffic` properties:** **`sales` properties:** **`advertising` properties:** **`tiktok` properties:** **`googleAds` properties:** **`latestAds[]` item properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `searchId` | `string` | Yes | Send it back instead of the image to read the next pages. Null when the search could not be kept. | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#search-shops-by-image # Search shops by image `POST /v1/shops/image-search` Finds the shops selling products that look like an image, the most active advertisers (Meta active ads) first, each with its most similar products. The storefronts of one brand come back as one row with otherStorefronts, billed once (groupBrands). Send the image as a multipart file or as a public URL; read the next pages with the returned searchId. Costs 4 credits per shop returned. **Tags:** Shops ## Request Body **Content-Type:** `multipart/form-data` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `image` | `string` | No | Image file (JPEG, PNG or WEBP, 10 MB max), sent as multipart/form-data. Provide exactly one of image, imageUrl or searchId. | | `imageUrl` | `string` | No | Public http(s) URL of the image. The server downloads it (10 MB max). | | `searchId` | `string` | No | searchId returned by a previous image search of this workspace. Replays the same image to read its next pages without sending it again. | | `offset` | `number` | No | | | `limit` | `number` | No | | | `groupBrands` | `boolean` | No | Count the storefronts of one brand (same root domain across countries, or the same Shopify store on several domains) as one shop. False keeps every storefront apart; the same store on several domains always counts once. | | `productsPerShop` | `number` | No | Most similar matching products returned with each shop. | **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `image` | `string` | No | Image file (JPEG, PNG or WEBP, 10 MB max), sent as multipart/form-data. Provide exactly one of image, imageUrl or searchId. | | `imageUrl` | `string` | No | Public http(s) URL of the image. The server downloads it (10 MB max). | | `searchId` | `string` | No | searchId returned by a previous image search of this workspace. Replays the same image to read its next pages without sending it again. | | `offset` | `number` | No | | | `limit` | `number` | No | | | `groupBrands` | `boolean` | No | Count the storefronts of one brand (same root domain across countries, or the same Shopify store on several domains) as one shop. False keeps every storefront apart; the same store on several domains always counts once. | | `productsPerShop` | `number` | No | Most similar matching products returned with each shop. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shop` | `object` | Yes | The storefront of the brand with the most active ads. | | `otherStorefronts` | `object`[] | Yes | The brand's other storefronts selling matching products (other countries or domains). Empty when groupBrands is false, unless one store is served on several domains. | | `bestSimilarityScore` | `number` | Yes | | | `matchingProducts` | `number` | Yes | Distinct products of the shop (or brand) that look like the image. | | `products` | `object`[] | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** **`catalog` properties:** **`traffic` properties:** **`sales` properties:** **`advertising` properties:** **`tiktok` properties:** **`googleAds` properties:** **`latestAds[]` item properties:** **`otherStorefronts[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `monthlyVisits` | `number` | Yes | | | `activeAds` | `number` | Yes | | **`products[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shopifyId` | `number` | Yes | | | `title` | `string` | Yes | | | `imageUrl` | `string` | Yes | | | `price` | `number` | Yes | | | `currency` | `string` | Yes | | | `similarityScore` | `number` | Yes | Cosine similarity between the query image and the product image (0.7 to 1). | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `searchId` | `string` | Yes | Send it back instead of the image to read the next pages. Null when the search could not be kept. | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#list-advertisers-linked-to-a-shop # List advertisers linked to a shop `GET /v1/shops/{shopId}/advertisers` Returns the linked advertiser summaries for a single shop identifier. **Tags:** Shops ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `limit` | query | No | `integer` | | ## Responses ### 200 - Linked advertisers response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `platform` | `facebook` | Yes | | | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `isPrimary` | `boolean` | Yes | | | `activeAds` | `number` | Yes | | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#get-shop-social-follower-history # Get shop social follower history `GET /v1/shops/{shopId}/socials/history` Returns follower time-series for Facebook and Instagram for the linked advertiser page of the shop. Other networks are handle-only today and not exposed here. **Tags:** Shops ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `period` | query | No | `day` \| `week` \| `month` | Aggregation bucket for the follower time series. Week and month pick the last raw snapshot of each bucket. | | `days` | query | No | `integer` | Rolling lookback window, in days, ending at the latest snapshot. | ## Responses ### 200 - Follower time-series response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `facebook` | `object`[] | Yes | Facebook follower snapshots ordered ascending by period. Empty when no Facebook page is linked to the shop. | | `instagram` | `object`[] | Yes | Instagram follower snapshots ordered ascending by period. Empty when the linked Facebook page has no connected Instagram account. | **`facebook[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `period` | `string` | Yes | ISO date string representing the period start. Month-first (YYYY-MM-DD) for monthly series, week-first for weekly series. | | `value` | `number` | Yes | | **`instagram[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `period` | `string` | Yes | ISO date string representing the period start. Month-first (YYYY-MM-DD) for monthly series, week-first for weekly series. | | `value` | `number` | Yes | | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#get-shop-sales-history # Get shop sales history `GET /v1/shops/{shopId}/sales/history` Returns the daily readings of the sales tracker for a shop: estimated revenue and units sold, each over the 30 days before the reading. Estimates, in USD. Costs 4 credits per call. **Tags:** Shops ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `period` | query | No | `day` \| `week` \| `month` | One reading per day, week or month. Week and month keep the last daily reading of each bucket; readings are never summed, since each one already covers the 30 days before it. | | `days` | query | No | `integer` | Rolling lookback window, in days, ending at the latest reading. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currency` | `USD` | Yes | | | `history` | `object`[] | Yes | Readings ordered ascending by date, ending on the current estimate. Empty when the sales tracker does not follow the shop. The history starts on 2026-09-18. | **`history[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | UTC day of the reading (YYYY-MM-DD). | | `estMonthlySales` | `number` | Yes | Estimated revenue over the 30 days before `date`, in whole USD. Not the revenue of that single day. | | `estMonthlySalesMin` | `number` | Yes | | | `estMonthlySalesMax` | `number` | Yes | | | `unitsSold` | `number` | Yes | Units sold over the same 30 days, as a floor. | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#list-shop-products # List shop products `GET /v1/shops/{shopId}/products` Returns the paginated list of Shopify best-selling products for a single shop. Products come from the shop’s Shopify best-seller feed and can be sorted by rank, price, or creation date. For estimated sales, ads and selling countries per product, use GET /v1/products?shopId={shopId}. **Tags:** Shops ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `limit` | query | No | `integer` | Maximum number of products to return per page. | | `offset` | query | No | `integer` | Offset into the products list. | | `sortBy` | query | No | `popularity` \| `price` \| `createdAt` | Sort key. `popularity` orders by Shopify best-seller rank; `price` by product price; `createdAt` by Shopify product creation date. | | `order` | query | No | `asc` \| `desc` | Sort direction. Defaults to `asc` for `popularity` and `desc` otherwise. | ## Responses ### 200 - Paginated shop products response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Upstream Shopify numeric product id (as a string). | | `title` | `string` | Yes | | | `handle` | `string` | Yes | Shopify product handle (URL slug). | | `imageUrl` | `string` | Yes | | | `productUrl` | `string` | Yes | | | `price` | `number` | Yes | | | `currency` | `string` | Yes | | | `rank` | `number` | Yes | Position of the product in the shop’s best-seller list, with 1 being the best seller. | | `createdAt` | `string` | Yes | Shopify product creation date. | | `publishedAt` | `string` | Yes | Shopify product publication date. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `offset` | `number` | Yes | | | `total` | `number` | Yes | | --- Tag: Shops · Reference: https://docs.trendtrack.io/docs/reference/api/shops#get-a-shop-by-id # Get a shop by id `GET /v1/shops/{shopId}` Returns the public hybrid shop detail read model for a single shop identifier. **Tags:** Shops ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | ## Responses ### 200 - Detailed public shop response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `trustpilot` | `object` | Yes | | | `socials` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | Yes | Current sales estimate. Null when the sales tracker does not follow the shop. For the daily history, call GET /v1/shops/{shopId}/sales/history. | | `advertising` | `object` | Yes | | | `technology` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | | `similarShops` | `object`[] | Yes | Preview of up to 6 shops ranked by similarity (relevance desc). For the full paginated list, call GET /v1/shops/{identifier}/similar using either the domain or public shop id. | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `isShopifyPlus` | `boolean` | Yes | | | `defaultLanguage` | `string` | Yes | | **`trustpilot` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `rating` | `number` | Yes | | | `reviewCount` | `number` | Yes | | | `brandName` | `string` | Yes | | | `brandLogo` | `string` | Yes | | | `url` | `string` | Yes | | **`socials` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `facebook` | `object` | Yes | | | `instagram` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `youtube` | `object` | Yes | | | `pinterest` | `object` | Yes | | | `linkedin` | `object` | Yes | | | `twitter` | `object` | Yes | | **`facebook` properties:** **`instagram` properties:** **`tiktok` properties:** **`youtube` properties:** **`pinterest` properties:** **`linkedin` properties:** **`twitter` properties:** **`catalog` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `productsCount` | `number` | Yes | | | `mainCategory` | `string` | Yes | | | `bestSellers` | `object`[] | Yes | Top best-selling products for this shop. Capped at 3 items. Sourced from `shopify_best_selling` when available, with fallback to `best_sellers_object` then `best_sellers` image URLs. | | `categories` | `string`[] | Yes | | | `myShopifyDomain` | `string` | Yes | | **`bestSellers[]` item properties:** **`traffic` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `monthlyVisits` | `number` | Yes | | | `growth30d` | `number` | Yes | | | `history` | `object`[] | Yes | Monthly visits time-series, sorted ascending by period. Capped at the 6 most recent months. | | `topCountries` | `object`[] | Yes | Top markets by traffic share (country code + share in [0, 1]). Derived from SimilarWeb geography breakdown when available, otherwise from the `countries` list with null shares. | | `growth90d` | `number` | Yes | | | `growth180d` | `number` | Yes | | | `mainMarkets` | `object`[] | Yes | Alias of `topCountries` kept for backwards compatibility with the detail endpoint. | **`history[]` item properties:** **`topCountries[]` item properties:** **`mainMarkets[]` item properties:** **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currency` | `USD` | Yes | The tracker converts every product price to USD. | | `estMonthlySales` | `number` | Yes | Estimated revenue over the last 30 days, in whole USD. An estimate from the sales tracker; 0 means the tracker measured no sales. | | `unitsSold` | `number` | Yes | Units sold over the same 30 days. A floor: the shop sold at least this many. | | `estMonthlySalesMin` | `number` | Yes | Low end of the 30-day revenue estimate, in whole USD. | | `estMonthlySalesMax` | `number` | Yes | High end of the 30-day revenue estimate, in whole USD. | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | | `linkedAdvertisersCount` | `number` | Yes | | | `history` | `object`[] | Yes | Weekly active-ads time-series, sorted ascending by period. Capped at the 26 most recent weekly points (~6 months). | | `topCountries` | `object`[] | Yes | Top countries by Meta ads volume (share in [0, 1]). Derived from the shop-level `ads_country_stats` aggregate across all linked advertisers. | | `linkedAdvertisers` | `object`[] | Yes | | | `summary` | `object` | Yes | | | `adsCountryStats` | `object`[] | Yes | Shop-level Meta ads country distribution from `ads_country_stats`. Distinct from `summary.countryDistribution`, which is derived from linked Facebook page reach. | **`history[]` item properties:** **`topCountries[]` item properties:** **`linkedAdvertisers[]` item properties:** **`summary` properties:** **`adsCountryStats[]` item properties:** **`technology` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `theme` | `string` | Yes | Canonical Shopify theme display name from the shop technology profile. | | `apps` | `object`[] | Yes | Shopify apps detected on the shop, with vendor icons. | | `pixels` | `object`[] | Yes | Pixels detected on the shop, resolved to human-readable names and icons via the public technologies vocabulary. | **`apps[]` item properties:** **`pixels[]` item properties:** **`tiktok` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `hasTikTok` | `boolean` | Yes | True when the shop has an indexed TikTok page/handle or TikTok rollup activity. This is independent from Meta advertising fields. | | `pageId` | `string` | Yes | | | `handle` | `string` | Yes | | | `profileMetrics` | `object` | Yes | | | `activity` | `object` | Yes | | | `lastUpdatedAt` | `string` | Yes | | **`profileMetrics` properties:** **`activity` properties:** **`latestAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `mediaType` | `image` \| `video` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | **`similarShops[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `shop` | `object` | Yes | | | `similarityScore` | `number` | Yes | | **`shop` properties:** --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#list-products # List products `GET /v1/products` Searches the products catalogue (the app's Products screen) by name, sorted by best-seller rank, recency, estimated sales, ad pressure or EU spend. Use POST /v1/products/query for every filter. **Tags:** Products ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `query` | query | No | `string` | Searched in product names. "a + b": all words; "a / b": at least one; "-c" excludes. | | `sortBy` | query | No | `relevance` \| `best-selling` \| `newest` \| `est-sales` \| `active-ads` \| `ad-pressure` \| `spend` \| `spend-14d` | relevance: estimated monthly revenue and active ads multiplied (ln(2 + revenue) × ln(2 + active ads)²), so a product needs both to rank high and active ads weigh the most; it multiplies the text match when query is set. best-selling: shop best-seller rank. newest: Shopify publish date. est-sales: estimated revenue. ad-pressure: share of the shop's active ads on the product. spend: EU ad spend (Pro plans and above). | | `order` | query | No | `asc` \| `desc` | Defaults to asc for best-selling, desc for the others. Missing values always come last. | | `shopId` | query | No | `string` | One shop's catalogue instead of the whole index. | | `limit` | query | No | `integer` | | | `cursor` | query | No | `string` | pagination.nextCursor of the previous page. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | {shopId}:{shopifyId}, or {shopId}:handle:{handle} without a Shopify id. Use it with /v1/products/{productId} and as a board item sourceId. | | `shopifyId` | `string` | Yes | | | `title` | `string` | Yes | | | `description` | `string` | Yes | | | `url` | `string` | Yes | | | `handle` | `string` | Yes | | | `imageUrl` | `string` | Yes | | | `publishedAt` | `string` | Yes | Shopify creation date, ISO 8601. | | `price` | `object` | Yes | | | `reviews` | `object` | Yes | | | `bestSellerRank` | `object` | Yes | | | `optionNames` | `string`[] | Yes | | | `sales` | `object` | Yes | | | `ads` | `object` | Yes | | | `euMetrics` | `object` | Yes | | | `weeklyHistory` | `object`[] | Yes | 26 weeks, oldest first. | | `shop` | `object` | Yes | | **`price` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `amount` | `number` | Yes | In the shop currency. | | `currency` | `string` | Yes | | | `amountUsd` | `number` | Yes | | | `compareAtAmount` | `number` | Yes | Compare-at price; null outside a promotion. | | `onSale` | `boolean` | Yes | | | `discountPercent` | `number` | Yes | 0-100, rounded; null outside a promotion. | | `isSubscription` | `boolean` | Yes | | | `promoTypes` | `percent-off` \| `bogo` \| `buy-x-get-y` \| `bundle` \| `free-gift` \| `free-shipping`[] | Yes | | **`reviews` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `rating` | `number` | Yes | | | `count` | `number` | Yes | | **`bestSellerRank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `position` | `number` | Yes | 1-100 in the shop's Shopify best-seller collection; null beyond. | | `percentile` | `number` | Yes | The rank over the shop catalogue, in %. | **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `dailyRevenueUsd` | `number` | Yes | Estimated revenue per day, USD. null: the sales tracker does not follow the product. | | `dailyRevenueRangeUsd` | `object` | Yes | Estimated revenue per day, USD. | | `monthlyRevenueUsd` | `number` | Yes | Estimated revenue over 30 days, USD. | | `dailyUnitsSold` | `number` | Yes | Units sold per day, rounded in tiers. | | `monthlyUnitsSold` | `number` | Yes | | **`dailyRevenueRangeUsd` properties:** **`ads` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `active` | `number` | Yes | null: no ad was ever linked to the product (unknown, not zero). | | `total` | `number` | Yes | | | `launched30d` | `number` | Yes | Ads launched over the last 30 days. | | `weekOverWeekGrowth` | `number` | Yes | Active ads, last week over the previous one, in %. | | `adShare` | `number` | Yes | Share of the shop's active ads pushing the product, in %. | | `advertisersCount` | `number` | Yes | Distinct Facebook pages pushing the product. | | `hasPartnershipAds` | `boolean` | Yes | | | `previewUrls` | `string`[] | Yes | | | `activeByCountry` | `object`[] | Yes | Active ads per targeted country, most first. | | `sellingCountries` | `string`[] | Yes | Countries the product's ads targeted, most pushed first. | **`activeByCountry[]` item properties:** **`euMetrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `locked` | `boolean` | Yes | true: the workspace plan does not open EU/UK data; the fields below are null, not zero. | | `spendUsd` | `number` | Yes | Total EU ad spend, USD: EU reach x CPM / 1000. | | `dailySpendUsd` | `number` | Yes | Average daily EU ad spend over the last two complete weeks, USD. | | `reach` | `number` | Yes | Total EU reach of the product's ads. | | `spendShare` | `number` | Yes | EU reach of the product over the EU reach of the pages pushing it, in %. | | `reachByCountry` | `object`[] | Yes | | **`reachByCountry[]` item properties:** **`weeklyHistory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `from` | `string` | Yes | | | `to` | `string` | Yes | | | `activeAds` | `number` | Yes | | | `euDailySpendUsd` | `number` | Yes | Average daily EU ad spend of the week, USD. Null for the week still running. | | `euDailyReach` | `number` | Yes | EU reach gained per day over the week. Null for the week still running. | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Use with /v1/shops/{shopId}. | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `productsCount` | `number` | Yes | | | `monthlyVisits` | `number` | Yes | | | `monthlyRevenueUsd` | `number` | Yes | Estimated shop revenue over 30 days, USD. | | `createdAt` | `string` | Yes | | | `categoryIds` | `number`[] | Yes | Google categories, most likely first (see /v1/facets/categories). | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalRelation` | `eq` \| `gte` | Yes | gte: total is a lower bound. | | `nextCursor` | `string` | Yes | Pass it as cursor for the next page; null on the last page. | --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#query-products # Query products `POST /v1/products/query` The products catalogue with every filter of the app's Products screen: price, reviews, best-seller rank, launch date, promotions, selling countries, estimated sales and units, ads (active, launched, share, partnership), EU/UK spend, and the shop's niche, traffic, origin and technologies. EU/UK data (euAdSpend, spendShare, sortBy=spend, euMetrics) opens on Pro plans and above. **Tags:** Products ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `query` | `string` | No | Searched in product names. "a + b": all words; "a / b": at least one; "-c" excludes. | | `sortBy` | `relevance` \| `best-selling` \| `newest` \| `est-sales` \| `active-ads` \| `ad-pressure` \| `spend` \| `spend-14d` | No | relevance: estimated monthly revenue and active ads multiplied (ln(2 + revenue) × ln(2 + active ads)²), so a product needs both to rank high and active ads weigh the most; it multiplies the text match when query is set. best-selling: shop best-seller rank. newest: Shopify publish date. est-sales: estimated revenue. ad-pressure: share of the shop's active ads on the product. spend: EU ad spend (Pro plans and above). | | `order` | `asc` \| `desc` | No | Defaults to asc for best-selling, desc for the others. Missing values always come last. | | `shopId` | `string` | No | One shop's catalogue instead of the whole index. | | `limit` | `integer` | No | | | `cursor` | `string` | No | pagination.nextCursor of the previous page. | | `searchFields` | `productName` \| `productDescription` \| `shop` \| `url`[] | No | Where query is searched. | | `cpm` | `number` | No | CPM (USD) turning EU reach into estimated spend. Defaults to 9. | | `subscription` | `subscription` \| `one-time` | No | | | `publishedAfter` | `string` | No | Shopify creation date, inclusive. | | `publishedBefore` | `string` | No | Shopify creation date, inclusive. | | `promoTypes` | `percent-off` \| `bogo` \| `buy-x-get-y` \| `bundle` \| `free-gift` \| `free-shipping`[] | No | Only percent-off (a compare-at price) is told apart; any other type finds nothing. | | `currencies` | `string`[] | No | Shop currency, ISO 4217. Values: /v1/products/facets. | | `shopCountries` | `string`[] | No | Shop origin, ISO alpha-2. Values: /v1/products/facets. | | `sellingCountries` | `string`[] | No | Countries where the product has active ads (or active EU/UK reach, see sellingCountriesBasis), ISO alpha-2. | | `mainSellingCountries` | `string`[] | No | The product's main selling country is one of these, ISO alpha-2. | | `excludeSellingCountries` | `string`[] | No | Countries where the product must not be active, ISO alpha-2. | | `sellingCountriesBasis` | `adCount` \| `reach` | No | adCount: countries with active ads. reach: EU/UK countries with active reach. | | `categoryIds` | `number`[] | No | Shop niche, Google category ids (/v1/facets/categories). | | `shopCreatedAfter` | `string` | No | Shop creation date, inclusive. | | `shopCreatedBefore` | `string` | No | Shop creation date, inclusive. | | `shopVisitorCountries` | `string`[] | No | The shop's top visitor countries, ISO alpha-2. Values: /v1/products/facets. | | `pixelIds` | `string`[] | No | Shop pixels (/v1/facets/pixels). | | `shopifyAppIds` | `string`[] | No | Shopify apps (/v1/facets/shopify-apps). | | `themeIds` | `string`[] | No | Shopify themes (/v1/facets/themes). | | `adsLaunchedPeriod` | `7d` \| `14d` \| `30d` \| `all` | No | Window of minAdsLaunched / maxAdsLaunched: 7, 14 or 30 days, or all time. Required with them. | | `minAdsLaunched` | `integer` | No | Minimum ads launched for the product over adsLaunchedPeriod. | | `maxAdsLaunched` | `integer` | No | Maximum ads launched for the product over adsLaunchedPeriod. | | `partnership` | `boolean` | No | true: at least one partnership ad. false: none known. | | `minPrice` | `number` | No | Minimum. Product price, USD. Products priced 0 are left out once set. | | `maxPrice` | `number` | No | Maximum. Product price, USD. Products priced 0 are left out once set. | | `minRating` | `number` | No | Minimum. Average review rating. | | `maxRating` | `number` | No | Maximum. Average review rating. | | `minReviewCount` | `integer` | No | Minimum. Number of reviews. | | `maxReviewCount` | `integer` | No | Maximum. Number of reviews. | | `minBestSellerRank` | `integer` | No | Minimum. Rank in the shop's Shopify best-seller collection, 1-100. | | `maxBestSellerRank` | `integer` | No | Maximum. Rank in the shop's Shopify best-seller collection, 1-100. | | `minMonthlyRevenue` | `number` | No | Minimum. Estimated revenue over the last 30 days, USD. Products the sales tracker does not follow never match. | | `maxMonthlyRevenue` | `number` | No | Maximum. Estimated revenue over the last 30 days, USD. Products the sales tracker does not follow never match. | | `minMonthlyUnitsSold` | `integer` | No | Minimum. Estimated units sold over the last 30 days. | | `maxMonthlyUnitsSold` | `integer` | No | Maximum. Estimated units sold over the last 30 days. | | `minActiveAds` | `integer` | No | Minimum. Active Meta ads pushing the product. | | `maxActiveAds` | `integer` | No | Maximum. Active Meta ads pushing the product. | | `minAdShare` | `number` | No | Minimum. Share of the shop's active ads pushing the product, in %. | | `maxAdShare` | `number` | No | Maximum. Share of the shop's active ads pushing the product, in %. | | `minEuAdSpend` | `number` | No | Minimum. Total EU ad spend, USD (EU reach x cpm / 1000). EU/UK data: Pro plans and above. | | `maxEuAdSpend` | `number` | No | Maximum. Total EU ad spend, USD (EU reach x cpm / 1000). EU/UK data: Pro plans and above. | | `minSpendShare` | `number` | No | Minimum. EU reach of the product over the EU reach of the pages pushing it, in %. EU/UK data: Pro plans and above. | | `maxSpendShare` | `number` | No | Maximum. EU reach of the product over the EU reach of the pages pushing it, in %. EU/UK data: Pro plans and above. | | `minShopMonthlyVisits` | `integer` | No | Minimum. Shop monthly visits. | | `maxShopMonthlyVisits` | `integer` | No | Maximum. Shop monthly visits. | | `minShopTrafficGrowth30d` | `number` | No | Minimum. Shop traffic change over 30 days, in % (negative for a decline). | | `maxShopTrafficGrowth30d` | `number` | No | Maximum. Shop traffic change over 30 days, in % (negative for a decline). | | `minShopProductsCount` | `integer` | No | Minimum. Number of products in the shop. | | `maxShopProductsCount` | `integer` | No | Maximum. Number of products in the shop. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | {shopId}:{shopifyId}, or {shopId}:handle:{handle} without a Shopify id. Use it with /v1/products/{productId} and as a board item sourceId. | | `shopifyId` | `string` | Yes | | | `title` | `string` | Yes | | | `description` | `string` | Yes | | | `url` | `string` | Yes | | | `handle` | `string` | Yes | | | `imageUrl` | `string` | Yes | | | `publishedAt` | `string` | Yes | Shopify creation date, ISO 8601. | | `price` | `object` | Yes | | | `reviews` | `object` | Yes | | | `bestSellerRank` | `object` | Yes | | | `optionNames` | `string`[] | Yes | | | `sales` | `object` | Yes | | | `ads` | `object` | Yes | | | `euMetrics` | `object` | Yes | | | `weeklyHistory` | `object`[] | Yes | 26 weeks, oldest first. | | `shop` | `object` | Yes | | **`price` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `amount` | `number` | Yes | In the shop currency. | | `currency` | `string` | Yes | | | `amountUsd` | `number` | Yes | | | `compareAtAmount` | `number` | Yes | Compare-at price; null outside a promotion. | | `onSale` | `boolean` | Yes | | | `discountPercent` | `number` | Yes | 0-100, rounded; null outside a promotion. | | `isSubscription` | `boolean` | Yes | | | `promoTypes` | `percent-off` \| `bogo` \| `buy-x-get-y` \| `bundle` \| `free-gift` \| `free-shipping`[] | Yes | | **`reviews` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `rating` | `number` | Yes | | | `count` | `number` | Yes | | **`bestSellerRank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `position` | `number` | Yes | 1-100 in the shop's Shopify best-seller collection; null beyond. | | `percentile` | `number` | Yes | The rank over the shop catalogue, in %. | **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `dailyRevenueUsd` | `number` | Yes | Estimated revenue per day, USD. null: the sales tracker does not follow the product. | | `dailyRevenueRangeUsd` | `object` | Yes | Estimated revenue per day, USD. | | `monthlyRevenueUsd` | `number` | Yes | Estimated revenue over 30 days, USD. | | `dailyUnitsSold` | `number` | Yes | Units sold per day, rounded in tiers. | | `monthlyUnitsSold` | `number` | Yes | | **`dailyRevenueRangeUsd` properties:** **`ads` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `active` | `number` | Yes | null: no ad was ever linked to the product (unknown, not zero). | | `total` | `number` | Yes | | | `launched30d` | `number` | Yes | Ads launched over the last 30 days. | | `weekOverWeekGrowth` | `number` | Yes | Active ads, last week over the previous one, in %. | | `adShare` | `number` | Yes | Share of the shop's active ads pushing the product, in %. | | `advertisersCount` | `number` | Yes | Distinct Facebook pages pushing the product. | | `hasPartnershipAds` | `boolean` | Yes | | | `previewUrls` | `string`[] | Yes | | | `activeByCountry` | `object`[] | Yes | Active ads per targeted country, most first. | | `sellingCountries` | `string`[] | Yes | Countries the product's ads targeted, most pushed first. | **`activeByCountry[]` item properties:** **`euMetrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `locked` | `boolean` | Yes | true: the workspace plan does not open EU/UK data; the fields below are null, not zero. | | `spendUsd` | `number` | Yes | Total EU ad spend, USD: EU reach x CPM / 1000. | | `dailySpendUsd` | `number` | Yes | Average daily EU ad spend over the last two complete weeks, USD. | | `reach` | `number` | Yes | Total EU reach of the product's ads. | | `spendShare` | `number` | Yes | EU reach of the product over the EU reach of the pages pushing it, in %. | | `reachByCountry` | `object`[] | Yes | | **`reachByCountry[]` item properties:** **`weeklyHistory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `from` | `string` | Yes | | | `to` | `string` | Yes | | | `activeAds` | `number` | Yes | | | `euDailySpendUsd` | `number` | Yes | Average daily EU ad spend of the week, USD. Null for the week still running. | | `euDailyReach` | `number` | Yes | EU reach gained per day over the week. Null for the week still running. | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Use with /v1/shops/{shopId}. | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `productsCount` | `number` | Yes | | | `monthlyVisits` | `number` | Yes | | | `monthlyRevenueUsd` | `number` | Yes | Estimated shop revenue over 30 days, USD. | | `createdAt` | `string` | Yes | | | `categoryIds` | `number`[] | Yes | Google categories, most likely first (see /v1/facets/categories). | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalRelation` | `eq` \| `gte` | Yes | gte: total is a lower bound. | | `nextCursor` | `string` | Yes | Pass it as cursor for the next page; null on the last page. | --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#list-product-filter-values # List product filter values `GET /v1/products/facets` Currencies, shop origins and shop visitor countries across the products catalogue, with product counts. **Tags:** Products ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currencies` | `object`[] | Yes | Values for the currencies filter. | | `shopCountries` | `object`[] | Yes | Values for the shopCountries filter. | | `shopVisitorCountries` | `object`[] | Yes | Values for the shopVisitorCountries filter. | **`currencies[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `value` | `string` | Yes | | | `count` | `number` | Yes | | **`shopCountries[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `value` | `string` | Yes | | | `count` | `number` | Yes | | **`shopVisitorCountries[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `value` | `string` | Yes | | | `count` | `number` | Yes | | --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#look-up-a-product-by-its-page-url # Look up a product by its page url `GET /v1/products/lookup` Finds the catalogue product behind a Shopify product page url, with its full sheet. Same payload as GET /v1/products/{productId}. **Tags:** Products ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `url` | query | Yes | `string` | A Shopify product page: https:///products/. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | {shopId}:{shopifyId}, or {shopId}:handle:{handle} without a Shopify id. Use it with /v1/products/{productId} and as a board item sourceId. | | `shopifyId` | `string` | Yes | | | `title` | `string` | Yes | | | `description` | `string` | Yes | | | `url` | `string` | Yes | | | `handle` | `string` | Yes | | | `imageUrl` | `string` | Yes | | | `publishedAt` | `string` | Yes | Shopify creation date, ISO 8601. | | `price` | `object` | Yes | | | `reviews` | `object` | Yes | | | `bestSellerRank` | `object` | Yes | | | `optionNames` | `string`[] | Yes | | | `sales` | `object` | Yes | | | `ads` | `object` | Yes | | | `euMetrics` | `object` | Yes | | | `weeklyHistory` | `object`[] | Yes | 26 weeks, oldest first. | | `shop` | `object` | Yes | | | `detail` | `object` | Yes | | **`price` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `amount` | `number` | Yes | In the shop currency. | | `currency` | `string` | Yes | | | `amountUsd` | `number` | Yes | | | `compareAtAmount` | `number` | Yes | Compare-at price; null outside a promotion. | | `onSale` | `boolean` | Yes | | | `discountPercent` | `number` | Yes | 0-100, rounded; null outside a promotion. | | `isSubscription` | `boolean` | Yes | | | `promoTypes` | `percent-off` \| `bogo` \| `buy-x-get-y` \| `bundle` \| `free-gift` \| `free-shipping`[] | Yes | | **`reviews` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `rating` | `number` | Yes | | | `count` | `number` | Yes | | **`bestSellerRank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `position` | `number` | Yes | 1-100 in the shop's Shopify best-seller collection; null beyond. | | `percentile` | `number` | Yes | The rank over the shop catalogue, in %. | **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `dailyRevenueUsd` | `number` | Yes | Estimated revenue per day, USD. null: the sales tracker does not follow the product. | | `dailyRevenueRangeUsd` | `object` | Yes | Estimated revenue per day, USD. | | `monthlyRevenueUsd` | `number` | Yes | Estimated revenue over 30 days, USD. | | `dailyUnitsSold` | `number` | Yes | Units sold per day, rounded in tiers. | | `monthlyUnitsSold` | `number` | Yes | | **`dailyRevenueRangeUsd` properties:** **`ads` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `active` | `number` | Yes | null: no ad was ever linked to the product (unknown, not zero). | | `total` | `number` | Yes | | | `launched30d` | `number` | Yes | Ads launched over the last 30 days. | | `weekOverWeekGrowth` | `number` | Yes | Active ads, last week over the previous one, in %. | | `adShare` | `number` | Yes | Share of the shop's active ads pushing the product, in %. | | `advertisersCount` | `number` | Yes | Distinct Facebook pages pushing the product. | | `hasPartnershipAds` | `boolean` | Yes | | | `previewUrls` | `string`[] | Yes | | | `activeByCountry` | `object`[] | Yes | Active ads per targeted country, most first. | | `sellingCountries` | `string`[] | Yes | Countries the product's ads targeted, most pushed first. | **`activeByCountry[]` item properties:** **`euMetrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `locked` | `boolean` | Yes | true: the workspace plan does not open EU/UK data; the fields below are null, not zero. | | `spendUsd` | `number` | Yes | Total EU ad spend, USD: EU reach x CPM / 1000. | | `dailySpendUsd` | `number` | Yes | Average daily EU ad spend over the last two complete weeks, USD. | | `reach` | `number` | Yes | Total EU reach of the product's ads. | | `spendShare` | `number` | Yes | EU reach of the product over the EU reach of the pages pushing it, in %. | | `reachByCountry` | `object`[] | Yes | | **`reachByCountry[]` item properties:** **`weeklyHistory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `from` | `string` | Yes | | | `to` | `string` | Yes | | | `activeAds` | `number` | Yes | | | `euDailySpendUsd` | `number` | Yes | Average daily EU ad spend of the week, USD. Null for the week still running. | | `euDailyReach` | `number` | Yes | EU reach gained per day over the week. Null for the week still running. | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Use with /v1/shops/{shopId}. | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `productsCount` | `number` | Yes | | | `monthlyVisits` | `number` | Yes | | | `monthlyRevenueUsd` | `number` | Yes | Estimated shop revenue over 30 days, USD. | | `createdAt` | `string` | Yes | | | `categoryIds` | `number`[] | Yes | Google categories, most likely first (see /v1/facets/categories). | **`detail` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `images` | `string`[] | Yes | Every merchant photo, in product page order. | | `productType` | `string` | Yes | | | `options` | `object`[] | Yes | | | `sellingPlans` | `object`[] | Yes | | | `mediaCount` | `number` | Yes | | | `shopActiveAds` | `number` | Yes | Active Meta ads of the shop: the Ad Share denominator. | | `dailySales` | `object`[] | Yes | Last 90 days, oldest first. | **`options[]` item properties:** **`sellingPlans[]` item properties:** **`dailySales[]` item properties:** --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#list-a-products-ads # List a product's ads `GET /v1/products/{productId}/ads` The Meta ads that link to the product page, newest first, in the /v1/ads format. Ad ids work with /v1/ads/{adId} and as board items. **Tags:** Products ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `productId` | path | Yes | `string` | The id returned by product search: {shopId}:{shopifyId}, or {shopId}:handle:{handle}. | | `status` | query | No | `active` \| `inactive` \| `all` | | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `product` | `object` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`product` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `title` | `string` | Yes | | | `url` | `string` | Yes | | | `landingPage` | `string` | Yes | The landing page the ads are matched on. null: the product has no page, so no ads. | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#create-a-product-share-link # Create a product share link `POST /v1/products/{productId}/share-links` Returns the public product sheet link, reusing the caller's active link for this product. The public sheet never carries EU/UK data. **Tags:** Products ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `productId` | path | Yes | `string` | The id returned by product search: {shopId}:{shopifyId}, or {shopId}:handle:{handle}. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `productId` | `string` | Yes | | | `url` | `string` | Yes | | | `createdAt` | `string` | Yes | | --- Tag: Products · Reference: https://docs.trendtrack.io/docs/reference/api/products#get-a-product # Get a product `GET /v1/products/{productId}` The product as search returns it, plus its sheet: every photo, options, subscription plans, and estimated sales day by day over 90 days. **Tags:** Products ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `productId` | path | Yes | `string` | The id returned by product search: {shopId}:{shopifyId}, or {shopId}:handle:{handle}. | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | {shopId}:{shopifyId}, or {shopId}:handle:{handle} without a Shopify id. Use it with /v1/products/{productId} and as a board item sourceId. | | `shopifyId` | `string` | Yes | | | `title` | `string` | Yes | | | `description` | `string` | Yes | | | `url` | `string` | Yes | | | `handle` | `string` | Yes | | | `imageUrl` | `string` | Yes | | | `publishedAt` | `string` | Yes | Shopify creation date, ISO 8601. | | `price` | `object` | Yes | | | `reviews` | `object` | Yes | | | `bestSellerRank` | `object` | Yes | | | `optionNames` | `string`[] | Yes | | | `sales` | `object` | Yes | | | `ads` | `object` | Yes | | | `euMetrics` | `object` | Yes | | | `weeklyHistory` | `object`[] | Yes | 26 weeks, oldest first. | | `shop` | `object` | Yes | | | `detail` | `object` | Yes | | **`price` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `amount` | `number` | Yes | In the shop currency. | | `currency` | `string` | Yes | | | `amountUsd` | `number` | Yes | | | `compareAtAmount` | `number` | Yes | Compare-at price; null outside a promotion. | | `onSale` | `boolean` | Yes | | | `discountPercent` | `number` | Yes | 0-100, rounded; null outside a promotion. | | `isSubscription` | `boolean` | Yes | | | `promoTypes` | `percent-off` \| `bogo` \| `buy-x-get-y` \| `bundle` \| `free-gift` \| `free-shipping`[] | Yes | | **`reviews` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `rating` | `number` | Yes | | | `count` | `number` | Yes | | **`bestSellerRank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `position` | `number` | Yes | 1-100 in the shop's Shopify best-seller collection; null beyond. | | `percentile` | `number` | Yes | The rank over the shop catalogue, in %. | **`sales` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `dailyRevenueUsd` | `number` | Yes | Estimated revenue per day, USD. null: the sales tracker does not follow the product. | | `dailyRevenueRangeUsd` | `object` | Yes | Estimated revenue per day, USD. | | `monthlyRevenueUsd` | `number` | Yes | Estimated revenue over 30 days, USD. | | `dailyUnitsSold` | `number` | Yes | Units sold per day, rounded in tiers. | | `monthlyUnitsSold` | `number` | Yes | | **`dailyRevenueRangeUsd` properties:** **`ads` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `active` | `number` | Yes | null: no ad was ever linked to the product (unknown, not zero). | | `total` | `number` | Yes | | | `launched30d` | `number` | Yes | Ads launched over the last 30 days. | | `weekOverWeekGrowth` | `number` | Yes | Active ads, last week over the previous one, in %. | | `adShare` | `number` | Yes | Share of the shop's active ads pushing the product, in %. | | `advertisersCount` | `number` | Yes | Distinct Facebook pages pushing the product. | | `hasPartnershipAds` | `boolean` | Yes | | | `previewUrls` | `string`[] | Yes | | | `activeByCountry` | `object`[] | Yes | Active ads per targeted country, most first. | | `sellingCountries` | `string`[] | Yes | Countries the product's ads targeted, most pushed first. | **`activeByCountry[]` item properties:** **`euMetrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `locked` | `boolean` | Yes | true: the workspace plan does not open EU/UK data; the fields below are null, not zero. | | `spendUsd` | `number` | Yes | Total EU ad spend, USD: EU reach x CPM / 1000. | | `dailySpendUsd` | `number` | Yes | Average daily EU ad spend over the last two complete weeks, USD. | | `reach` | `number` | Yes | Total EU reach of the product's ads. | | `spendShare` | `number` | Yes | EU reach of the product over the EU reach of the pages pushing it, in %. | | `reachByCountry` | `object`[] | Yes | | **`reachByCountry[]` item properties:** **`weeklyHistory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `from` | `string` | Yes | | | `to` | `string` | Yes | | | `activeAds` | `number` | Yes | | | `euDailySpendUsd` | `number` | Yes | Average daily EU ad spend of the week, USD. Null for the week still running. | | `euDailyReach` | `number` | Yes | EU reach gained per day over the week. Null for the week still running. | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Use with /v1/shops/{shopId}. | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `currency` | `string` | Yes | | | `productsCount` | `number` | Yes | | | `monthlyVisits` | `number` | Yes | | | `monthlyRevenueUsd` | `number` | Yes | Estimated shop revenue over 30 days, USD. | | `createdAt` | `string` | Yes | | | `categoryIds` | `number`[] | Yes | Google categories, most likely first (see /v1/facets/categories). | **`detail` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `images` | `string`[] | Yes | Every merchant photo, in product page order. | | `productType` | `string` | Yes | | | `options` | `object`[] | Yes | | | `sellingPlans` | `object`[] | Yes | | | `mediaCount` | `number` | Yes | | | `shopActiveAds` | `number` | Yes | Active Meta ads of the shop: the Ad Share denominator. | | `dailySales` | `object`[] | Yes | Last 90 days, oldest first. | **`options[]` item properties:** **`sellingPlans[]` item properties:** **`dailySales[]` item properties:** --- Tag: TikTok · Reference: https://docs.trendtrack.io/docs/reference/api/tiktok#list-tiktok-library-items # List TikTok library items `GET /v1/tiktok/library` Returns TikTok ads and organic videos from the Public API TikTok library. This namespace is separate from the Meta-only /v1/ads endpoints and is backed by the tiktoks-search Elasticsearch alias. **Tags:** TikTok ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `search`, `searchArea` - Sorting: `sortBy`, `order` - Filters: `type`, `status`, `mediaTypes`, `languages`, `countries`, `hashtags`, `tiktokPageId`, `domain`, `handle`, `publishedAfter`, `publishedBefore`, `minViews`, `maxViews`, `minEngagementRate`, `maxEngagementRate` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `search` | query | No | `string` | | | `searchArea` | query | No | `all` \| `caption` \| `profile` \| `hashtag` \| `music` | | | `type` | query | No | `all` \| `ad` \| `organic` | | | `status` | query | No | `all` \| `active` \| `inactive` | | | `mediaTypes` | query | No | `image` \| `video` \| `carousel`[] | | | `languages` | query | No | `string`[] | ISO 639-1 codes (en, fr) or English language names (English, french), case-insensitive. | | `countries` | query | No | `string`[] | | | `hashtags` | query | No | `string`[] | Hashtags with or without #, case-insensitive. | | `tiktokPageId` | query | No | `string` | | | `domain` | query | No | `string` | | | `handle` | query | No | `string` | | | `publishedAfter` | query | No | `string` | | | `publishedBefore` | query | No | `string` | | | `minViews` | query | No | `integer` | | | `maxViews` | query | No | `integer` | | | `minEngagementRate` | query | No | `number` | | | `maxEngagementRate` | query | No | `number` | | | `sortBy` | query | No | `relevance` \| `newest` \| `updatedAt` \| `views` \| `likes` \| `comments` \| `shares` \| `saves` \| `engagementRate` \| `daysRunning` \| `followers` | | | `order` | query | No | `asc` \| `desc` | | | `page` | query | No | `object` | | | `limit` | query | No | `object` | | ## Responses ### 200 - Paginated TikTok library response. One returned TikTok item is one billable ads credit. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `tiktokId` | `string` | Yes | | | `type` | `ad` \| `organic` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | | | `isPinned` | `boolean` | Yes | | | `publishedAt` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `daysRunning` | `number` | Yes | | | `media` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `profile` | `object` | Yes | | | `shop` | `object` | Yes | | | `pin` | `object` | Yes | | | `pageSnapshot` | `object` | Yes | | | `indexedAt` | `string` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `videoUrl` | `string` | Yes | | | `imageUrls` | `string`[] | Yes | | | `medias` | `object`[] | Yes | | | `durationSec` | `number` | Yes | | | `mediaCount` | `number` | Yes | | | `imageCount` | `number` | Yes | | **`medias[]` item properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `description` | `string` | Yes | | | `language` | `string` | Yes | | | `category` | `string` | Yes | | | `hashtags` | `string`[] | Yes | | | `music` | `object` | Yes | | **`music` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `comments` | `number` | Yes | | | `saves` | `number` | Yes | | | `shares` | `number` | Yes | | | `reposts` | `number` | Yes | | | `engagementRate` | `number` | Yes | Percentage, not fraction. | | `rank` | `number` | Yes | | | `rankPercent` | `number` | Yes | | | `relevanceScore` | `number` | Yes | | | `deltaRank3d` | `number` | Yes | | | `deltaRank7d` | `number` | Yes | | | `deltaRank14d` | `number` | Yes | | | `deltaRank30d` | `number` | Yes | | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `handle` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `bio` | `string` | Yes | | | `bioUrl` | `string` | Yes | | | `accountType` | `string` | Yes | | | `secUid` | `string` | Yes | | | `followers` | `number` | Yes | | | `following` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `newTikToks` | `number` | Yes | | | `percentAds` | `number` | Yes | | | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `pageCreation` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `faviconUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `monthlyVisits` | `number` | Yes | | | `trafficGrowth30d` | `number` | Yes | | | `productsCount` | `number` | Yes | | | `googleCategoryIds` | `number`[] | Yes | | **`pin` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isCurrent` | `boolean` | Yes | | | `firstPinnedAt` | `string` | Yes | | | `lastPinnedAt` | `string` | Yes | | | `lastUnpinnedAt` | `string` | Yes | | **`pageSnapshot` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `recordedAt` | `string` | Yes | | | `adsCount` | `number` | Yes | | | `organicCount` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `dailyViews` | `number` | Yes | | | `dailyLikes` | `number` | Yes | | | `dailyFollowers` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: TikTok · Reference: https://docs.trendtrack.io/docs/reference/api/tiktok#query-tiktok-library-items # Query TikTok library items `POST /v1/tiktok/library/query` Advanced TikTok library query over ES-backed fields only. It intentionally does not use the internal Next /api/tiktok-ads route or per-request Postgres hydration. **Tags:** TikTok ## Request Body **Content-Type:** `application/json` **Find active TikTok ads by caption text:** ```json { "search": [ "protein gummies" ], "searchArea": "caption", "type": "ad", "status": "active", "minViews": 10000, "sortBy": "views", "order": "desc", "limit": 10 } ``` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `search` | `string`[] | No | | | `keywordMode` | `any` \| `all` | No | | | `searchArea` | `all` \| `caption` \| `profile` \| `hashtag` \| `music` | No | | | `type` | `all` \| `ad` \| `organic` | No | | | `status` | `all` \| `active` \| `inactive` | No | | | `mediaTypes` | `image` \| `video` \| `carousel`[] | No | | | `languages` | `string`[] | No | ISO 639-1 codes (en, fr) or English language names (English, french), case-insensitive. | | `countries` | `string`[] | No | | | `categories` | `string`[] | No | TikTok content categories, case-insensitive. | | `hashtags` | `string`[] | No | | | `tiktokPageIds` | `string`[] | No | | | `tiktokPageId` | `string` | No | | | `websiteId` | `string` | No | | | `domain` | `string` | No | | | `handle` | `string` | No | | | `hasShopLinked` | `yes` \| `no` | No | | | `publishedAfter` | `string` | No | | | `publishedBefore` | `string` | No | | | `updatedAfter` | `string` | No | | | `updatedBefore` | `string` | No | | | `minDaysRunning` | `number` | No | | | `maxDaysRunning` | `number` | No | | | `minViews` | `number` | No | | | `maxViews` | `number` | No | | | `minLikes` | `number` | No | | | `minShares` | `number` | No | | | `minEngagementRate` | `number` | No | | | `maxEngagementRate` | `number` | No | | | `minFollowers` | `number` | No | | | `minProfileViews` | `number` | No | | | `isPinned` | `boolean` | No | | | `sortBy` | `relevance` \| `newest` \| `updatedAt` \| `views` \| `likes` \| `comments` \| `shares` \| `saves` \| `engagementRate` \| `daysRunning` \| `followers` | No | | | `order` | `asc` \| `desc` | No | | | `page` | `object` | No | | | `limit` | `object` | No | | ## Responses ### 200 - Paginated TikTok library query response. One returned TikTok item is one billable ads credit. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `tiktokId` | `string` | Yes | | | `type` | `ad` \| `organic` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | | | `isPinned` | `boolean` | Yes | | | `publishedAt` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `daysRunning` | `number` | Yes | | | `media` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `profile` | `object` | Yes | | | `shop` | `object` | Yes | | | `pin` | `object` | Yes | | | `pageSnapshot` | `object` | Yes | | | `indexedAt` | `string` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `videoUrl` | `string` | Yes | | | `imageUrls` | `string`[] | Yes | | | `medias` | `object`[] | Yes | | | `durationSec` | `number` | Yes | | | `mediaCount` | `number` | Yes | | | `imageCount` | `number` | Yes | | **`medias[]` item properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `description` | `string` | Yes | | | `language` | `string` | Yes | | | `category` | `string` | Yes | | | `hashtags` | `string`[] | Yes | | | `music` | `object` | Yes | | **`music` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `comments` | `number` | Yes | | | `saves` | `number` | Yes | | | `shares` | `number` | Yes | | | `reposts` | `number` | Yes | | | `engagementRate` | `number` | Yes | Percentage, not fraction. | | `rank` | `number` | Yes | | | `rankPercent` | `number` | Yes | | | `relevanceScore` | `number` | Yes | | | `deltaRank3d` | `number` | Yes | | | `deltaRank7d` | `number` | Yes | | | `deltaRank14d` | `number` | Yes | | | `deltaRank30d` | `number` | Yes | | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `handle` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `bio` | `string` | Yes | | | `bioUrl` | `string` | Yes | | | `accountType` | `string` | Yes | | | `secUid` | `string` | Yes | | | `followers` | `number` | Yes | | | `following` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `newTikToks` | `number` | Yes | | | `percentAds` | `number` | Yes | | | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `pageCreation` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `faviconUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `monthlyVisits` | `number` | Yes | | | `trafficGrowth30d` | `number` | Yes | | | `productsCount` | `number` | Yes | | | `googleCategoryIds` | `number`[] | Yes | | **`pin` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isCurrent` | `boolean` | Yes | | | `firstPinnedAt` | `string` | Yes | | | `lastPinnedAt` | `string` | Yes | | | `lastUnpinnedAt` | `string` | Yes | | **`pageSnapshot` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `recordedAt` | `string` | Yes | | | `adsCount` | `number` | Yes | | | `organicCount` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `dailyViews` | `number` | Yes | | | `dailyLikes` | `number` | Yes | | | `dailyFollowers` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: TikTok · Reference: https://docs.trendtrack.io/docs/reference/api/tiktok#get-a-tiktok-library-item # Get a TikTok library item `GET /v1/tiktok/library/{itemId}` Returns one TikTok library item detail by composite_ad_id, with tiktok_id fallback because tiktok_id is part of the tiktoks-search public ES contract. **Tags:** TikTok ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `itemId` | path | Yes | `string` | | ## Responses ### 200 - TikTok library detail response. One found TikTok item is one billable ads credit. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `tiktokId` | `string` | Yes | | | `type` | `ad` \| `organic` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | | | `isPinned` | `boolean` | Yes | | | `publishedAt` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `daysRunning` | `number` | Yes | | | `media` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `profile` | `object` | Yes | | | `shop` | `object` | Yes | | | `pin` | `object` | Yes | | | `pageSnapshot` | `object` | Yes | | | `indexedAt` | `string` | Yes | | | `links` | `object` | Yes | | | `source` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `videoUrl` | `string` | Yes | | | `imageUrls` | `string`[] | Yes | | | `medias` | `object`[] | Yes | | | `durationSec` | `number` | Yes | | | `mediaCount` | `number` | Yes | | | `imageCount` | `number` | Yes | | **`medias[]` item properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `description` | `string` | Yes | | | `language` | `string` | Yes | | | `category` | `string` | Yes | | | `hashtags` | `string`[] | Yes | | | `music` | `object` | Yes | | **`music` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `comments` | `number` | Yes | | | `saves` | `number` | Yes | | | `shares` | `number` | Yes | | | `reposts` | `number` | Yes | | | `engagementRate` | `number` | Yes | Percentage, not fraction. | | `rank` | `number` | Yes | | | `rankPercent` | `number` | Yes | | | `relevanceScore` | `number` | Yes | | | `deltaRank3d` | `number` | Yes | | | `deltaRank7d` | `number` | Yes | | | `deltaRank14d` | `number` | Yes | | | `deltaRank30d` | `number` | Yes | | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `handle` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `bio` | `string` | Yes | | | `bioUrl` | `string` | Yes | | | `accountType` | `string` | Yes | | | `secUid` | `string` | Yes | | | `followers` | `number` | Yes | | | `following` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `newTikToks` | `number` | Yes | | | `percentAds` | `number` | Yes | | | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `pageCreation` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `faviconUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `monthlyVisits` | `number` | Yes | | | `trafficGrowth30d` | `number` | Yes | | | `productsCount` | `number` | Yes | | | `googleCategoryIds` | `number`[] | Yes | | **`pin` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isCurrent` | `boolean` | Yes | | | `firstPinnedAt` | `string` | Yes | | | `lastPinnedAt` | `string` | Yes | | | `lastUnpinnedAt` | `string` | Yes | | **`pageSnapshot` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `recordedAt` | `string` | Yes | | | `adsCount` | `number` | Yes | | | `organicCount` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `dailyViews` | `number` | Yes | | | `dailyLikes` | `number` | Yes | | | `dailyFollowers` | `number` | Yes | | **`links` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `tiktokUrl` | `string` | Yes | | | `profileUrl` | `string` | Yes | | **`source` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `network` | `string` | Yes | | | `sourceType` | `string` | Yes | | | `tiktokPageId` | `string` | Yes | | | `websiteId` | `string` | Yes | | | `domain` | `string` | Yes | | --- Tag: TikTok · Reference: https://docs.trendtrack.io/docs/reference/api/tiktok#list-tiktok-library-items-for-a-shop # List TikTok library items for a shop `GET /v1/shops/{shopId}/tiktok/library` Returns TikTok library items linked to one public shop id using exact ES shop identifiers. This route has a TikTok endpoint key and ads entitlement even though it is nested under /v1/shops. **Tags:** TikTok ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `search`, `searchArea` - Sorting: `sortBy`, `order` - Filters: `type`, `status`, `mediaTypes`, `languages`, `countries`, `hashtags`, `tiktokPageId`, `domain`, `handle`, `publishedAfter`, `publishedBefore`, `minViews`, `maxViews`, `minEngagementRate`, `maxEngagementRate` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `search` | query | No | `string` | | | `searchArea` | query | No | `all` \| `caption` \| `profile` \| `hashtag` \| `music` | | | `type` | query | No | `all` \| `ad` \| `organic` | | | `status` | query | No | `all` \| `active` \| `inactive` | | | `mediaTypes` | query | No | `image` \| `video` \| `carousel`[] | | | `languages` | query | No | `string`[] | ISO 639-1 codes (en, fr) or English language names (English, french), case-insensitive. | | `countries` | query | No | `string`[] | | | `hashtags` | query | No | `string`[] | Hashtags with or without #, case-insensitive. | | `tiktokPageId` | query | No | `string` | | | `domain` | query | No | `string` | | | `handle` | query | No | `string` | | | `publishedAfter` | query | No | `string` | | | `publishedBefore` | query | No | `string` | | | `minViews` | query | No | `number` | | | `maxViews` | query | No | `number` | | | `minEngagementRate` | query | No | `number` | | | `maxEngagementRate` | query | No | `number` | | | `sortBy` | query | No | `relevance` \| `newest` \| `updatedAt` \| `views` \| `likes` \| `comments` \| `shares` \| `saves` \| `engagementRate` \| `daysRunning` \| `followers` | | | `order` | query | No | `asc` \| `desc` | | | `page` | query | No | `object` | | | `limit` | query | No | `object` | | ## Responses ### 200 - Paginated shop-scoped TikTok library response. One returned TikTok item is one billable ads credit. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `tiktokId` | `string` | Yes | | | `type` | `ad` \| `organic` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | | | `isPinned` | `boolean` | Yes | | | `publishedAt` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `daysRunning` | `number` | Yes | | | `media` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `profile` | `object` | Yes | | | `shop` | `object` | Yes | | | `pin` | `object` | Yes | | | `pageSnapshot` | `object` | Yes | | | `indexedAt` | `string` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `videoUrl` | `string` | Yes | | | `imageUrls` | `string`[] | Yes | | | `medias` | `object`[] | Yes | | | `durationSec` | `number` | Yes | | | `mediaCount` | `number` | Yes | | | `imageCount` | `number` | Yes | | **`medias[]` item properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `description` | `string` | Yes | | | `language` | `string` | Yes | | | `category` | `string` | Yes | | | `hashtags` | `string`[] | Yes | | | `music` | `object` | Yes | | **`music` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `comments` | `number` | Yes | | | `saves` | `number` | Yes | | | `shares` | `number` | Yes | | | `reposts` | `number` | Yes | | | `engagementRate` | `number` | Yes | Percentage, not fraction. | | `rank` | `number` | Yes | | | `rankPercent` | `number` | Yes | | | `relevanceScore` | `number` | Yes | | | `deltaRank3d` | `number` | Yes | | | `deltaRank7d` | `number` | Yes | | | `deltaRank14d` | `number` | Yes | | | `deltaRank30d` | `number` | Yes | | **`profile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `handle` | `string` | Yes | | | `name` | `string` | Yes | | | `avatarUrl` | `string` | Yes | | | `bio` | `string` | Yes | | | `bioUrl` | `string` | Yes | | | `accountType` | `string` | Yes | | | `secUid` | `string` | Yes | | | `followers` | `number` | Yes | | | `following` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `newTikToks` | `number` | Yes | | | `percentAds` | `number` | Yes | | | `views` | `number` | Yes | | | `likes` | `number` | Yes | | | `pageCreation` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `faviconUrl` | `string` | Yes | | | `countryCode` | `string` | Yes | | | `monthlyVisits` | `number` | Yes | | | `trafficGrowth30d` | `number` | Yes | | | `productsCount` | `number` | Yes | | | `googleCategoryIds` | `number`[] | Yes | | **`pin` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isCurrent` | `boolean` | Yes | | | `firstPinnedAt` | `string` | Yes | | | `lastPinnedAt` | `string` | Yes | | | `lastUnpinnedAt` | `string` | Yes | | **`pageSnapshot` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `recordedAt` | `string` | Yes | | | `adsCount` | `number` | Yes | | | `organicCount` | `number` | Yes | | | `totalTikToks` | `number` | Yes | | | `dailyViews` | `number` | Yes | | | `dailyLikes` | `number` | Yes | | | `dailyFollowers` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Emails · Reference: https://docs.trendtrack.io/docs/reference/api/emails#query-emails # Query emails `POST /v1/emails/query` Returns the advanced public emails discovery surface. This endpoint is the canonical public route for richer email filters while keeping the response aligned with the stable public EmailSummary contract. The API does not expose opens, clicks, conversions, or revenue metrics; sorting is discovery-oriented metadata ordering, not best-performance scoring. **Tags:** Emails ## Request Body **Content-Type:** `application/json` **Find recent promotional emails from high-traffic shops:** ```json { "search": [ "welcome", "discount" ], "searchType": "email", "keywordMode": "any", "sortBy": "newest", "order": "desc", "minMonthlyVisits": 20000, "promotionTypes": [ "Discount" ], "shopifyPlan": "plus", "page": 1, "limit": 25 } ``` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `search` | `string`[] | No | | | `searchType` | `domain` \| `email` \| `shopKeywords` | No | Search mode for this request. Allowed values: `domain`, `email`, `shopKeywords`. | | `keywordMode` | `any` \| `all` | No | How multiple search keywords are combined. Allowed values: `any`, `all`. | | `sortBy` | `newest` \| `oldest` \| `relevance` \| `monthlyVisits` \| `bodyLength` \| `shopEmailFrequency` \| `event` \| `promotionType` | No | Sort key for this request. Allowed values: `newest`, `oldest`, `relevance`, `monthlyVisits`, `bodyLength`, `shopEmailFrequency`, `event`, `promotionType`. These are discovery/indexing sorts, not opens/clicks/conversions performance rankings. | | `order` | `asc` \| `desc` | No | Sort direction for this request. Allowed values: `asc`, `desc`. | | `page` | `number` | No | | | `limit` | `number` | No | | | `sentAfter` | `string` | No | | | `sentBefore` | `string` | No | | | `campaignTypes` | `string`[] | No | | | `languages` | `string`[] | No | | | `promotionTypes` | `string`[] | No | Stored promotion type names, matched case-insensitively (`Discount %`, `Discount % With Threshold`, `Free Delivery`, `BOGO`, `Bundle Deal`, `No Promotion`, …). | | `promotionTypeIds` | `number`[] | No | | | `categories` | `string`[] | No | Stored email category names, matched case-insensitively (`Promotional Campaign`, `Product Campaign`, `Launch Campaign`, `Relational Campaign`, `Event Campaign`, `Win-back Campaign`, `Survey`). | | `emailCategoryIds` | `number`[] | No | | | `eventNames` | `string`[] | No | | | `eventIds` | `number`[] | No | | | `eventCategories` | `string`[] | No | | | `minBodyLength` | `number` | No | | | `maxBodyLength` | `number` | No | | | `shopIds` | `string`[] | No | Stable public shop identifiers. | | `minMonthlyVisits` | `number` | No | | | `maxMonthlyVisits` | `number` | No | | | `trafficGrowth` | `string` | No | Traffic growth filter DSL using public rolling windows. Valid periods: `last30d`, `last90d`, `last180d`. | | `minProductsCount` | `number` | No | | | `maxProductsCount` | `number` | No | | | `creationCountries` | `string`[] | No | | | `excludeCreationCountries` | `string`[] | No | | | `currencies` | `string`[] | No | | | `shopDefaultLanguages` | `string`[] | No | | | `mainMarketCountries` | `string`[] | No | | | `amongMarketCountries` | `string`[] | No | | | `excludeMarketCountries` | `string`[] | No | | | `visitorCountries` | `string`[] | No | Alias of amongMarketCountries: matches shops with any of these countries among their markets. No separate visitor-country data is indexed. | | `shopCreatedAfter` | `string` | No | | | `shopCreatedBefore` | `string` | No | | | `technologies` | `string`[] | No | Main e-commerce platform slugs or ids (shopify, woocommerce, wordpress, magento, wix, …). Only the shop's main platform is indexed for emails; other technologies are rejected with unsupported_filter. | | `shopifyPlan` | `all` \| `plus` \| `nonPlus` | No | Enum value accepted by this request. Allowed values: `all`, `plus`, `nonPlus`. | | `categoryIds` | `number`[] | No | | | `minShopEmails90d` | `number` | No | | | `maxShopEmails90d` | `number` | No | | | `minAvgEmailsPerWeek` | `number` | No | | | `maxAvgEmailsPerWeek` | `number` | No | | | `minActiveAds` | `number` | No | | | `maxActiveAds` | `number` | No | | | `adsGrowth` | `string` | No | Ads growth filter DSL using public rolling windows. Valid periods: `last7d`, `last30d`, `last90d`. | | `minTrustpilotRating` | `number` | No | | | `maxTrustpilotRating` | `number` | No | | | `minTrustpilotReviewCount` | `number` | No | | | `maxTrustpilotReviewCount` | `number` | No | | ## Responses ### 200 - Paginated advanced emails query response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `sentAt` | `string` | Yes | | | `campaignType` | `string` | Yes | | | `classification` | `object` | Yes | | | `content` | `object` | Yes | | | `shop` | `object` | Yes | | **`classification` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `promotionType` | `string` | Yes | | | `promotionTypeId` | `number` | Yes | | | `category` | `string` | Yes | | | `categoryId` | `number` | Yes | | | `event` | `object` | Yes | | **`event` properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `subject` | `string` | Yes | | | `preheader` | `string` | Yes | | | `bodyPreview` | `string` | Yes | | | `bodyLength` | `number` | Yes | | | `screenshotUrl` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Emails · Reference: https://docs.trendtrack.io/docs/reference/api/emails#get-raw-email-html-by-id # Get raw email HTML by id `GET /v1/emails/{emailId}/html` Returns the raw captured HTML for one public email identifier. Existing emails may have html=null when raw HTML is unavailable. **Tags:** Emails ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `emailId` | path | Yes | `string` | Stable public email identifier. | ## Responses ### 200 - Raw email HTML response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `emailId` | `number` | Yes | Stable public email identifier. | | `html` | `object` | Yes | Raw captured HTML for the email, when available. | | `htmlLength` | `number` | Yes | Length of the raw HTML string in characters. Zero when HTML is unavailable. | --- Tag: Emails · Reference: https://docs.trendtrack.io/docs/reference/api/emails#get-an-email-by-id # Get an email by id `GET /v1/emails/{emailId}` Returns one public email detail object by stable email identifier, including the clean public shop context nested under the email. **Tags:** Emails ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `emailId` | path | Yes | `string` | Stable public email identifier. | ## Responses ### 200 - Public email detail response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `sentAt` | `string` | Yes | | | `campaignType` | `string` | Yes | | | `classification` | `object` | Yes | | | `content` | `object` | Yes | | | `shop` | `object` | Yes | | | `language` | `string` | Yes | | **`classification` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `promotionType` | `string` | Yes | | | `promotionTypeId` | `number` | Yes | | | `category` | `string` | Yes | | | `categoryId` | `number` | Yes | | | `event` | `object` | Yes | | **`event` properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `subject` | `string` | Yes | | | `preheader` | `string` | Yes | | | `bodyPreview` | `string` | Yes | | | `bodyLength` | `number` | Yes | | | `screenshotUrl` | `string` | Yes | | | `body` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `traffic` | `object` | Yes | | | `catalog` | `object` | Yes | | | `marketing` | `object` | Yes | | | `technology` | `object` | Yes | | | `trustpilot` | `object` | Yes | | | `analytics` | `object` | Yes | | **`profile` properties:** **`traffic` properties:** **`catalog` properties:** **`marketing` properties:** **`technology` properties:** **`trustpilot` properties:** **`analytics` properties:** --- Tag: Emails · Reference: https://docs.trendtrack.io/docs/reference/api/emails#list-emails-for-a-shop # List emails for a shop `GET /v1/shops/{shopId}/emails` Returns the paginated public emails linked to one shop identifier, with stable recency-oriented filters and the same public EmailSummary response contract as the global emails surface. **Tags:** Emails ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `search` - Sorting: `sortBy` - Filters: `sentAfter`, `sentBefore`, `campaignTypes`, `languages` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `search` | query | No | `string`[] | Optional email search keywords. Repeated query params and comma-separated values are both accepted. | | `sortBy` | query | No | `newest` \| `oldest` \| `relevance` \| `event` \| `promotionType` | Sort key for this request. Allowed values: `newest`, `oldest`, `relevance`, `event`, `promotionType`. These are discovery/indexing sorts, not opens/clicks/conversions performance rankings. | | `sentAfter` | query | No | `string` | | | `sentBefore` | query | No | `string` | | | `campaignTypes` | query | No | `string`[] | | | `languages` | query | No | `string`[] | | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | ## Responses ### 200 - Paginated shop emails response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `sentAt` | `string` | Yes | | | `campaignType` | `string` | Yes | | | `classification` | `object` | Yes | | | `content` | `object` | Yes | | | `shop` | `object` | Yes | | **`classification` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `promotionType` | `string` | Yes | | | `promotionTypeId` | `number` | Yes | | | `category` | `string` | Yes | | | `categoryId` | `number` | Yes | | | `event` | `object` | Yes | | **`event` properties:** **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `subject` | `string` | Yes | | | `preheader` | `string` | Yes | | | `bodyPreview` | `string` | Yes | | | `bodyLength` | `number` | Yes | | | `screenshotUrl` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Emails · Reference: https://docs.trendtrack.io/docs/reference/api/emails#get-shop-email-stats # Get shop email stats `GET /v1/shops/{shopId}/emails/stats` Returns shop-scoped 90-day email frequency stats and sparse UTC calendar counts for one requested month. **Tags:** Emails ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `shopId` | path | Yes | `string` | Stable public shop identifier. | | `month` | query | Yes | `string` | Calendar month to aggregate, formatted as YYYY-MM. | ## Responses ### 200 - Shop email stats response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `last90Days` | `object` | Yes | | | `calendar` | `object` | Yes | | **`last90Days` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `totalEmails` | `number` | Yes | Total emails sent by this shop in the trailing 90 days. | | `avgEmailsPerWeek` | `number` | Yes | Average emails sent per week over the trailing 90 days. | | `emailsByDayOfWeek` | `object` | Yes | Emails sent by day of week using 0=Sunday ... 6=Saturday. | **`calendar` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `month` | `string` | Yes | Calendar month represented by this aggregate. | | `totalEmails` | `number` | Yes | Total emails sent in the requested calendar month. | | `emailsByDate` | `object` | Yes | Sparse UTC calendar counts keyed by YYYY-MM-DD. Dates with zero emails are omitted. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#create-a-brandtracker # Create a brandtracker `POST /v1/brandtrackers` Creates or reactivates a workspace brandtracker by exactly one target identifier: facebookPageId, websiteId, shopId (alias of websiteId), or domain. Domains are normalized and must resolve to exactly one known website. State-changing create/reactivate requests consume one brandtracker create/delete quota unit and one active brandtracker slot; already-active no-ops return 200 and cost 0 units. **Tags:** Brandtrackers ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `facebookPageId` | `string` | No | Meta/Facebook page identifier to track. Exactly one of facebookPageId, websiteId, shopId, or domain is required. | | `websiteId` | `string` | No | Website/shop identifier to track as a shop-level brandtracker. Exactly one target identifier is accepted. | | `shopId` | `string` | No | Alias of websiteId for shop-oriented clients. Exactly one target identifier is accepted. | | `domain` | `string` | No | Shop domain to resolve to exactly one known website and track as a shop-level brandtracker. Protocols, paths, and a leading www. are normalized away. | | `folderId` | `number` | No | Workspace brandtracker folder id. Null or omitted attaches the brandtracker at root. | ## Responses ### 200 - Brandtracker creation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | True when this call created or reactivated a workspace brandtracker; false when an active link already existed. | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `workspaceLinkId` | `number` | No | Workspace link identifier. Present on mutation responses and useful for follow-up move/delete operations. | | `targetType` | `shop` \| `page` | No | Resolved tracked target type. Present on mutation responses. | | `websiteId` | `string` | No | Resolved website/shop identifier when the brandtracker target is shop-level. | | `domain` | `string` | No | Resolved canonical domain when the brandtracker target is shop-level. | | `avatarUrl` | `string` | Yes | | | `status` | `object` | Yes | | | `workspaceAddedAt` | `string` | Yes | | | `folder` | `object` | Yes | Primary folder membership, ordered by folder rank, name, then id. Null when the tracked brand has no folder memberships. | | `advertising` | `object` | Yes | | | `websites` | `object`[] | Yes | | | `totalTraffic` | `number` | Yes | | **`status` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isLoaded` | `boolean` | Yes | | | `lastCrawledAt` | `string` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | | `newAdsLastDay` | `number` | Yes | | | `newAdsLast7Days` | `number` | Yes | | | `newAdsLast30Days` | `number` | Yes | | **`websites[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `siteName` | `string` | Yes | | | `trafficNumber` | `number` | Yes | | | `trafficChange` | `number` | Yes | | | `monthlyTraffic` | `object` | Yes | | | `socialNetworks` | `object` | Yes | | **`socialNetworks` properties:** ### 201 - Brandtracker created or reactivated. Already-active idempotent calls return 200 with created=false. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | True when this call created or reactivated a workspace brandtracker; false when an active link already existed. | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `workspaceLinkId` | `number` | No | Workspace link identifier. Present on mutation responses and useful for follow-up move/delete operations. | | `targetType` | `shop` \| `page` | No | Resolved tracked target type. Present on mutation responses. | | `websiteId` | `string` | No | Resolved website/shop identifier when the brandtracker target is shop-level. | | `domain` | `string` | No | Resolved canonical domain when the brandtracker target is shop-level. | | `avatarUrl` | `string` | Yes | | | `status` | `object` | Yes | | | `workspaceAddedAt` | `string` | Yes | | | `folder` | `object` | Yes | Primary folder membership, ordered by folder rank, name, then id. Null when the tracked brand has no folder memberships. | | `advertising` | `object` | Yes | | | `websites` | `object`[] | Yes | | | `totalTraffic` | `number` | Yes | | **`status` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isLoaded` | `boolean` | Yes | | | `lastCrawledAt` | `string` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | | `newAdsLastDay` | `number` | Yes | | | `newAdsLast7Days` | `number` | Yes | | | `newAdsLast30Days` | `number` | Yes | | **`websites[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `siteName` | `string` | Yes | | | `trafficNumber` | `number` | Yes | | | `trafficChange` | `number` | Yes | | | `monthlyTraffic` | `object` | Yes | | | `socialNetworks` | `object` | Yes | | **`socialNetworks` properties:** --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtrackers # List brandtrackers `GET /v1/brandtrackers` Returns the workspace-scoped active brandtrackers attached to the authenticated public API workspace. The public identifier is brandtracker.id; legacy spyders.uuid values are accepted when migration metadata exists. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `hasNewAdsSince` | query | No | `string` | ISO date/time lower bound. Returns brandtrackers with positive new-ad deltas recorded on or after this timestamp. | | `name` | query | No | `string` | Case-insensitive contains match against brandtracker name. | | `sortBy` | query | No | `newAdsLastDay` \| `newAdsLast7Days` \| `newAdsLast30Days` \| `activeAds` \| `totalTraffic` \| `name` \| `createdAt` | Sort key. Metric and createdAt sorts are descending; name sorts ascending. Omit to preserve default workspace ordering. | | `folderIds` | query | No | `integer`[] | Folder ids. Repeated query params and comma-separated values are both accepted. | | `folderNames` | query | No | `string`[] | Folder name search terms. Matches are case-insensitive contains checks. Repeated query params and comma-separated values are both accepted. | ## Responses ### 200 - Paginated brandtrackers response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `workspaceLinkId` | `number` | No | Workspace link identifier. Present on mutation responses and useful for follow-up move/delete operations. | | `targetType` | `shop` \| `page` | No | Resolved tracked target type. Present on mutation responses. | | `websiteId` | `string` | No | Resolved website/shop identifier when the brandtracker target is shop-level. | | `domain` | `string` | No | Resolved canonical domain when the brandtracker target is shop-level. | | `avatarUrl` | `string` | Yes | | | `status` | `object` | Yes | | | `workspaceAddedAt` | `string` | Yes | | | `folder` | `object` | Yes | Primary folder membership, ordered by folder rank, name, then id. Null when the tracked brand has no folder memberships. | | `advertising` | `object` | Yes | | | `websites` | `object`[] | Yes | | | `totalTraffic` | `number` | Yes | | **`status` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isLoaded` | `boolean` | Yes | | | `lastCrawledAt` | `string` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | | `newAdsLastDay` | `number` | Yes | | | `newAdsLast7Days` | `number` | Yes | | | `newAdsLast30Days` | `number` | Yes | | **`websites[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `siteName` | `string` | Yes | | | `trafficNumber` | `number` | Yes | | | `trafficChange` | `number` | Yes | | | `monthlyTraffic` | `object` | Yes | | | `socialNetworks` | `object` | Yes | | **`socialNetworks` properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#create-a-brandtracker-folder # Create a brandtracker folder `POST /v1/brandtrackers/folders` Creates a workspace brandtracker folder and assigns the next rank atomically. Folder mutations are workspace-scoped, metered, and audited. **Tags:** Brandtrackers ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | Yes | Workspace-scoped folder name. Rank is assigned atomically as the next workspace rank. | ## Responses ### 200 - Brandtracker folder creation response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `rank` | `number` | Yes | | | `brandtrackerCount` | `number` | Yes | Number of active brandtrackers currently assigned to this folder. | ### 201 - Brandtracker folder created. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `rank` | `number` | Yes | | | `brandtrackerCount` | `number` | Yes | Number of active brandtrackers currently assigned to this folder. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtracker-folders # List brandtracker folders `GET /v1/brandtrackers/folders` Returns the active workspace brandtracker folders so clients can resolve folder ids for brandtracker filters. Equivalent folder listing is also available at GET /v1/workspace/folders. **Tags:** Brandtrackers ## Responses ### 200 - Brandtracker folders. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `rank` | `number` | Yes | | | `brandtrackerCount` | `number` | Yes | Number of active brandtrackers currently assigned to this folder. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#rename-a-brandtracker-folder # Rename a brandtracker folder `PATCH /v1/brandtrackers/folders/{folderId}` Renames a workspace brandtracker folder. The folder id must belong to the authenticated workspace; cross-workspace ids are returned as not found before any state change. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `integer` | | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | Yes | New workspace-scoped folder name. | ## Responses ### 200 - Brandtracker folder rename response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | | `rank` | `number` | Yes | | | `brandtrackerCount` | `number` | Yes | Number of active brandtrackers currently assigned to this folder. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#delete-a-brandtracker-folder # Delete a brandtracker folder `DELETE /v1/brandtrackers/folders/{folderId}` Deletes a workspace folder. move-to-default moves active brandtrackers to root; delete-brandtrackers deactivates affected workspace links. confirm must be true. The delete-brandtrackers action consumes one persistent brandtracker create/delete quota operation for the whole folder and decrements active brandtracker usage by the affected active-link count; no partial mutation is committed when quota is exhausted. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `integer` | | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `action` | `move-to-default` \| `delete-brandtrackers` | Yes | move-to-default keeps affected trackers active and clears their folder. delete-brandtrackers deactivates affected active workspace links, consumes one persistent create/delete quota unit for the whole folder delete, and decrements active brandtracker usage by affectedCount. | | `confirm` | `boolean` | Yes | Must be true for destructive folder delete requests. | ## Responses ### 200 - Brandtracker folder delete response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `deleted` | `boolean` | Yes | | | `action` | `move-to-default` \| `delete-brandtrackers` | Yes | | | `affectedCount` | `number` | Yes | Number of active workspace links moved to root or deactivated by the folder delete action. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#replace-brandtracker-folder-memberships # Replace brandtracker folder memberships `PATCH /v1/brandtrackers/workspace-links` Moves active workspace brandtracker links by exactly one address set: brandtrackerIds or workspaceLinkIds. The destination folder id must belong to the authenticated workspace; null moves links to root. Move operations are metered and audited but do not consume persistent create/delete quota or change active brandtracker usage. **Tags:** Brandtrackers ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtrackerIds` | `string`[] | No | Public brandtracker ids to move. Exactly one of brandtrackerIds or workspaceLinkIds is required. | | `workspaceLinkIds` | `number`[] | No | Workspace link ids to move. Exactly one of brandtrackerIds or workspaceLinkIds is required. | | `folderId` | `number` | Yes | Destination workspace folder id, or null to move to root. | ## Responses ### 200 - Brandtracker workspace-link move response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedCount` | `number` | Yes | Deduplicated number of requested ids in the submitted address set. | | `affectedCount` | `number` | Yes | Number of active workspace links changed. Cross-workspace, inactive, or unknown ids are excluded and reported as not found where safe. | | `notFoundBrandtrackerIds` | `string`[] | No | Requested public brandtracker ids that did not resolve to active links in this workspace. | | `notFoundWorkspaceLinkIds` | `number`[] | No | Requested workspace link ids that did not resolve to active links in this workspace. | | `cooldownUntil` | `string` | No | Removals only: the removed brands keep their slots until this time (24h cooldown). | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#bulk-delete-brandtracker-workspace-links # Bulk delete brandtracker workspace links `DELETE /v1/brandtrackers/workspace-links` Deactivates active workspace brandtracker links by exactly one address set: brandtrackerIds or workspaceLinkIds. confirm must be true. Bulk delete consumes one persistent brandtracker create/delete quota operation for the request, reports requested/affected/not-found ids, and decrements active brandtracker usage by the affected active-link count. **Tags:** Brandtrackers ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtrackerIds` | `string`[] | No | Public brandtracker ids to delete. Exactly one of brandtrackerIds or workspaceLinkIds is required. | | `workspaceLinkIds` | `number`[] | No | Workspace link ids to delete. Exactly one of brandtrackerIds or workspaceLinkIds is required. | | `confirm` | `boolean` | Yes | Must be true for destructive bulk delete requests. | ## Responses ### 200 - Brandtracker workspace-link delete response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedCount` | `number` | Yes | Deduplicated number of requested ids in the submitted address set. | | `affectedCount` | `number` | Yes | Number of active workspace links changed. Cross-workspace, inactive, or unknown ids are excluded and reported as not found where safe. | | `notFoundBrandtrackerIds` | `string`[] | No | Requested public brandtracker ids that did not resolve to active links in this workspace. | | `notFoundWorkspaceLinkIds` | `number`[] | No | Requested workspace link ids that did not resolve to active links in this workspace. | | `cooldownUntil` | `string` | No | Removals only: the removed brands keep their slots until this time (24h cooldown). | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#delete-a-brandtracker # Delete a brandtracker `DELETE /v1/brandtrackers/{brandtrackerId}` Marks the workspace brandtracker inactive while preserving the workspace link and workspace-scoped metadata for reconstructability/reactivation. The shared global brandtracker row is preserved. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | ## Responses ### 200 - Brandtracker delete response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `deleted` | `boolean` | Yes | | | `cooldownUntil` | `string` | Yes | The removed brand keeps its tracked-brand slot until this time (24h cooldown); the slot still counts against the plan limit, and re-adding the same brand before then reuses it. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-a-brandtracker # Get a brandtracker `GET /v1/brandtrackers/{brandtrackerId}` Returns the detail payload for one active workspace brandtracker resolved from brandtracker.id. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | ## Responses ### 200 - Brandtracker detail response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `workspaceLinkId` | `number` | No | Workspace link identifier. Present on mutation responses and useful for follow-up move/delete operations. | | `targetType` | `shop` \| `page` | No | Resolved tracked target type. Present on mutation responses. | | `websiteId` | `string` | No | Resolved website/shop identifier when the brandtracker target is shop-level. | | `domain` | `string` | No | Resolved canonical domain when the brandtracker target is shop-level. | | `avatarUrl` | `string` | Yes | | | `status` | `object` | Yes | | | `workspaceAddedAt` | `string` | Yes | | | `folder` | `object` | Yes | Primary folder membership, ordered by folder rank, name, then id. Null when the tracked brand has no folder memberships. | | `advertising` | `object` | Yes | | | `websites` | `object`[] | Yes | | | `totalTraffic` | `number` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `pageProfile` | `object` | Yes | | | `statistics` | `object` | Yes | | **`status` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isLoaded` | `boolean` | Yes | | | `lastCrawledAt` | `string` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | | `newAdsLastDay` | `number` | Yes | | | `newAdsLast7Days` | `number` | Yes | | | `newAdsLast30Days` | `number` | Yes | | **`websites[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `siteName` | `string` | Yes | | | `trafficNumber` | `number` | Yes | | | `trafficChange` | `number` | Yes | | | `monthlyTraffic` | `object` | Yes | | | `socialNetworks` | `object` | Yes | | **`socialNetworks` properties:** **`pageProfile` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `about` | `string` | Yes | | | `category` | `string` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | | `instagramUsername` | `string` | Yes | | | `profileUri` | `string` | Yes | | | `runningAds` | `number` | Yes | | **`statistics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `urlCount` | `object` | Yes | | | `ctaCount` | `object` | Yes | | | `liveAdCount` | `object` | Yes | | | `formatCount` | `object` | Yes | | | `euData` | `object` | Yes | | **`liveAdCount` properties:** --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtrackers-in-a-folder # List brandtrackers in a folder `GET /v1/brandtrackers/folders/{folderId}/brandtrackers` Returns the workspace-scoped active brandtrackers assigned to the requested folder. This is equivalent to /v1/brandtrackers?folderIds=:folderId. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `integer` | Workspace brandtracker folder id. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `hasNewAdsSince` | query | No | `string` | ISO date/time lower bound. Returns brandtrackers with positive new-ad deltas recorded on or after this timestamp. | | `name` | query | No | `string` | Case-insensitive contains match against brandtracker name. | | `sortBy` | query | No | `newAdsLastDay` \| `newAdsLast7Days` \| `newAdsLast30Days` \| `activeAds` \| `totalTraffic` \| `name` \| `createdAt` | Sort key. Metric and createdAt sorts are descending; name sorts ascending. Omit to preserve default workspace ordering. | ## Responses ### 200 - Paginated folder brandtrackers response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `workspaceLinkId` | `number` | No | Workspace link identifier. Present on mutation responses and useful for follow-up move/delete operations. | | `targetType` | `shop` \| `page` | No | Resolved tracked target type. Present on mutation responses. | | `websiteId` | `string` | No | Resolved website/shop identifier when the brandtracker target is shop-level. | | `domain` | `string` | No | Resolved canonical domain when the brandtracker target is shop-level. | | `avatarUrl` | `string` | Yes | | | `status` | `object` | Yes | | | `workspaceAddedAt` | `string` | Yes | | | `folder` | `object` | Yes | Primary folder membership, ordered by folder rank, name, then id. Null when the tracked brand has no folder memberships. | | `advertising` | `object` | Yes | | | `websites` | `object`[] | Yes | | | `totalTraffic` | `number` | Yes | | **`status` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isLoaded` | `boolean` | Yes | | | `lastCrawledAt` | `string` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `name` | `string` | Yes | | **`advertising` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | | `newAdsLastDay` | `number` | Yes | | | `newAdsLast7Days` | `number` | Yes | | | `newAdsLast30Days` | `number` | Yes | | **`websites[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `siteName` | `string` | Yes | | | `trafficNumber` | `number` | Yes | | | `trafficChange` | `number` | Yes | | | `monthlyTraffic` | `object` | Yes | | | `socialNetworks` | `object` | Yes | | **`socialNetworks` properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtracker-snapshot-dates # List brandtracker snapshot dates `GET /v1/brandtrackers/{brandtrackerId}/snapshots` Returns available ad reach snapshot dates and readiness status for one active workspace brandtracker. latestDate is preserved as a compatibility alias of latestReadyDate; snapshotDate=latest resolves to the latest ready date. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of snapshot dates to return. Defaults to 100. | ## Responses ### 200 - Paginated brandtracker snapshot dates response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `pagination` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `latestDate` | `string` | Yes | Deprecated compatibility alias of latestReadyDate. Latest ready snapshot date for this brandtracker, or null when no ready snapshots exist. | | `latestReadyDate` | `string` | Yes | Latest collection day of this brandtracker's pages within the history the workspace may read, or null when none was collected. Reach (EU/UK ads only) does not affect it. | | `latestScheduledDate` | `string` | Yes | Latest collection day of this brandtracker's pages. Equal to latestReadyDate: a collected day is complete, so no day is indexed without being ready. | | `dates` | `string`[] | Yes | Available snapshot dates in descending order. Preserved for backwards compatibility; mirrors snapshots[].date. | | `snapshots` | `object`[] | Yes | Snapshot dates with readiness status and row counts in descending date order. | **`snapshots[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | Snapshot date in YYYY-MM-DD format. | | `status` | `ready` \| `indexing` \| `scheduled` | Yes | Readiness status. ready means the brandtracker's pages were collected that day, with every page aggregate; indexing and scheduled are reserved and not currently returned. | | `usableRows` | `number` | Yes | Pages of this brandtracker collected on this snapshot date. Reach is only published for EU/UK ads and is not required. | | `indexedRows` | `number` | Yes | Pages of this brandtracker collected on this snapshot date. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtracker-ads # List brandtracker ads `GET /v1/brandtrackers/{brandtrackerId}/ads` Returns the Meta ads for one active workspace brandtracker resolved from brandtracker.id to fb_page_id. The response reuses the public ad summary shape. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `keywordMode` - Time and snapshots: `createdAfter`, `createdBefore`, `spendPeriod`, `spendPerPagePeriod`, `snapshotDate` - Sorting: `sortBy` - Filters: `status`, `mediaType`, `keywords`, `minDaysRunning`, `maxDaysRunning`, `minDuplicates`, `maxDuplicates`, `landingPages`, `adLanguage`, `cta`, `adCopyHashes`, `adCountries`, `mainCountries`, `euOnly`, `partners`, `partnerIds`, `minReach`, `maxReach`, `cpm`, `minSpend`, `maxSpend`, `minSpendPerPage`, `maxSpendPerPage`, `hideLowReach`, `minAge`, `maxAge`, `sex`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minVideoDuration`, `maxVideoDuration`, `minDescriptionLength`, `maxDescriptionLength`, `linkedDomain`, `growthRank` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `sortBy` | query | No | `newest` \| `createdAt` \| `longestRunning` \| `reach` \| `duplicates` \| `adOrder` \| `relevance` | Sort key. The adOrder value also accepts ad_order and ad-order aliases. | | `status` | query | No | `all` \| `active` \| `inactive` | Status filter for this request. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Enum value accepted by this request. Allowed values: `all`, `image`, `video`. | | `keywords` | query | No | `string`[] | Keyword search terms. Repeated query params and comma-separated values are both accepted. | | `keywordMode` | query | No | `any` \| `all` | Enum value accepted by this request. Allowed values: `any`, `all`. | | `createdAfter` | query | No | `string` | | | `createdBefore` | query | No | `string` | | | `minDaysRunning` | query | No | `integer` | | | `maxDaysRunning` | query | No | `integer` | | | `minDuplicates` | query | No | `integer` | | | `maxDuplicates` | query | No | `integer` | | | `landingPages` | query | No | `string`[] | Landing page URLs. Repeated query params and comma-separated values are both accepted. | | `adLanguage` | query | No | `string`[] | Ad languages. Repeated query params and comma-separated values are both accepted. | | `cta` | query | No | `string`[] | Call-to-action labels. Repeated query params and comma-separated values are both accepted. | | `adCopyHashes` | query | No | `string`[] | 12-character MD5 prefixes for ad copy descriptions. | | `adCountries` | query | No | `string` | Comma-separated country include/exclude filters. | | `mainCountries` | query | No | `string`[] | Main ad countries. Repeated query params and comma-separated values are both accepted. | | `euOnly` | query | No | `boolean` | When true, keep only ads flagged as EU ads. | | `partners` | query | No | `boolean` | When true, keep only partnership ads. When false, keep only non-partnership ads. | | `partnerIds` | query | No | `string`[] | Partner identifiers. Repeated query params and comma-separated values are both accepted. | | `minReach` | query | No | `integer` | Minimum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `maxReach` | query | No | `integer` | Maximum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `cpm` | query | No | `number` | CPM used to convert spend filters into reach thresholds. | | `minSpend` | query | No | `number` | | | `maxSpend` | query | No | `number` | | | `spendPeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | query | No | `number` | | | `maxSpendPerPage` | query | No | `number` | | | `spendPerPagePeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `hideLowReach` | query | No | `boolean` | When true, hides ads flagged as low reach. | | `minAge` | query | No | `integer` | | | `maxAge` | query | No | `integer` | | | `sex` | query | No | `men` \| `women` \| `all` | Enum value accepted by this request. Allowed values: `men`, `women`, `all`. | | `minFacebookLikes` | query | No | `integer` | | | `maxFacebookLikes` | query | No | `integer` | | | `minInstagramFollowers` | query | No | `integer` | | | `maxInstagramFollowers` | query | No | `integer` | | | `minVideoDuration` | query | No | `number` | | | `maxVideoDuration` | query | No | `number` | | | `minDescriptionLength` | query | No | `integer` | | | `maxDescriptionLength` | query | No | `integer` | | | `linkedDomain` | query | No | `string` | Linked domain filter. URLs are normalized to their hostname before validation. | | `growthRank` | query | No | `rising` \| `falling` \| `stable`[] | Rank trend filters. Repeated query params and comma-separated values are both accepted. | | `snapshotDate` | query | No | `string` | Snapshot date (YYYY-MM-DD or latest). When present, status is interpreted as active at this date. | ## Responses ### 200 - Paginated brandtracker ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtracker-partnership-ads # List brandtracker partnership ads `GET /v1/brandtrackers/{brandtrackerId}/partnership-ads` Returns deduped Meta partnership ad groups for one active workspace brandtracker. This endpoint always filters to ads with a partner badge and reuses the public ad summary shape. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `keywordMode` - Time and snapshots: `createdAfter`, `createdBefore`, `spendPeriod`, `spendPerPagePeriod`, `snapshotDate` - Sorting: `sortBy` - Filters: `status`, `mediaType`, `keywords`, `minDaysRunning`, `maxDaysRunning`, `minDuplicates`, `maxDuplicates`, `landingPages`, `adLanguage`, `cta`, `adCopyHashes`, `adCountries`, `mainCountries`, `euOnly`, `partnerIds`, `minReach`, `maxReach`, `cpm`, `minSpend`, `maxSpend`, `minSpendPerPage`, `maxSpendPerPage`, `hideLowReach`, `minAge`, `maxAge`, `sex`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minVideoDuration`, `maxVideoDuration`, `minDescriptionLength`, `maxDescriptionLength`, `linkedDomain`, `growthRank`, `partnerId` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `sortBy` | query | No | `newest` \| `createdAt` \| `longestRunning` \| `reach` \| `duplicates` \| `adOrder` \| `relevance` | Sort key. The adOrder value also accepts ad_order and ad-order aliases. | | `status` | query | No | `all` \| `active` \| `inactive` | Status filter for this request. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Enum value accepted by this request. Allowed values: `all`, `image`, `video`. | | `keywords` | query | No | `string`[] | Keyword search terms. Repeated query params and comma-separated values are both accepted. | | `keywordMode` | query | No | `any` \| `all` | Enum value accepted by this request. Allowed values: `any`, `all`. | | `createdAfter` | query | No | `string` | | | `createdBefore` | query | No | `string` | | | `minDaysRunning` | query | No | `integer` | | | `maxDaysRunning` | query | No | `integer` | | | `minDuplicates` | query | No | `integer` | | | `maxDuplicates` | query | No | `integer` | | | `landingPages` | query | No | `string`[] | Landing page URLs. Repeated query params and comma-separated values are both accepted. | | `adLanguage` | query | No | `string`[] | Ad languages. Repeated query params and comma-separated values are both accepted. | | `cta` | query | No | `string`[] | Call-to-action labels. Repeated query params and comma-separated values are both accepted. | | `adCopyHashes` | query | No | `string`[] | 12-character MD5 prefixes for ad copy descriptions. | | `adCountries` | query | No | `string` | Comma-separated country include/exclude filters. | | `mainCountries` | query | No | `string`[] | Main ad countries. Repeated query params and comma-separated values are both accepted. | | `euOnly` | query | No | `boolean` | When true, keep only ads flagged as EU ads. | | `partnerIds` | query | No | `string`[] | Partner identifiers. Repeated query params and comma-separated values are both accepted. | | `minReach` | query | No | `integer` | Minimum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `maxReach` | query | No | `integer` | Maximum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `cpm` | query | No | `number` | CPM used to convert spend filters into reach thresholds. | | `minSpend` | query | No | `number` | | | `maxSpend` | query | No | `number` | | | `spendPeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | query | No | `number` | | | `maxSpendPerPage` | query | No | `number` | | | `spendPerPagePeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `hideLowReach` | query | No | `boolean` | When true, hides ads flagged as low reach. | | `minAge` | query | No | `integer` | | | `maxAge` | query | No | `integer` | | | `sex` | query | No | `men` \| `women` \| `all` | Enum value accepted by this request. Allowed values: `men`, `women`, `all`. | | `minFacebookLikes` | query | No | `integer` | | | `maxFacebookLikes` | query | No | `integer` | | | `minInstagramFollowers` | query | No | `integer` | | | `maxInstagramFollowers` | query | No | `integer` | | | `minVideoDuration` | query | No | `number` | | | `maxVideoDuration` | query | No | `number` | | | `minDescriptionLength` | query | No | `integer` | | | `maxDescriptionLength` | query | No | `integer` | | | `linkedDomain` | query | No | `string` | Linked domain filter. URLs are normalized to their hostname before validation. | | `growthRank` | query | No | `rising` \| `falling` \| `stable`[] | Rank trend filters. Repeated query params and comma-separated values are both accepted. | | `snapshotDate` | query | No | `string` | Snapshot date (YYYY-MM-DD or latest). When present, status is interpreted as active at this date. | | `partnerId` | query | No | `string` | Single partner identifier alias. It is merged with partnerIds when both are provided. | ## Responses ### 200 - Paginated brandtracker partnership ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#count-brandtracker-partnership-ads # Count brandtracker partnership ads `GET /v1/brandtrackers/{brandtrackerId}/partnership-ads/count` Returns the deduped public ad group count matching the partnership ads list filters. This intentionally matches public list pagination semantics rather than the webapp raw active badge count. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Search: `keywordMode` - Time and snapshots: `createdAfter`, `createdBefore`, `spendPeriod`, `spendPerPagePeriod`, `snapshotDate` - Filters: `status`, `mediaType`, `keywords`, `minDaysRunning`, `maxDaysRunning`, `minDuplicates`, `maxDuplicates`, `landingPages`, `adLanguage`, `cta`, `adCopyHashes`, `adCountries`, `mainCountries`, `euOnly`, `partnerIds`, `minReach`, `maxReach`, `cpm`, `minSpend`, `maxSpend`, `minSpendPerPage`, `maxSpendPerPage`, `hideLowReach`, `minAge`, `maxAge`, `sex`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minVideoDuration`, `maxVideoDuration`, `minDescriptionLength`, `maxDescriptionLength`, `linkedDomain`, `growthRank`, `partnerId` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `status` | query | No | `all` \| `active` \| `inactive` | Status filter for this request. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Enum value accepted by this request. Allowed values: `all`, `image`, `video`. | | `keywords` | query | No | `string`[] | Keyword search terms. Repeated query params and comma-separated values are both accepted. | | `keywordMode` | query | No | `any` \| `all` | Enum value accepted by this request. Allowed values: `any`, `all`. | | `createdAfter` | query | No | `string` | | | `createdBefore` | query | No | `string` | | | `minDaysRunning` | query | No | `integer` | | | `maxDaysRunning` | query | No | `integer` | | | `minDuplicates` | query | No | `integer` | | | `maxDuplicates` | query | No | `integer` | | | `landingPages` | query | No | `string`[] | Landing page URLs. Repeated query params and comma-separated values are both accepted. | | `adLanguage` | query | No | `string`[] | Ad languages. Repeated query params and comma-separated values are both accepted. | | `cta` | query | No | `string`[] | Call-to-action labels. Repeated query params and comma-separated values are both accepted. | | `adCopyHashes` | query | No | `string`[] | 12-character MD5 prefixes for ad copy descriptions. | | `adCountries` | query | No | `string` | Comma-separated country include/exclude filters. | | `mainCountries` | query | No | `string`[] | Main ad countries. Repeated query params and comma-separated values are both accepted. | | `euOnly` | query | No | `boolean` | When true, keep only ads flagged as EU ads. | | `partnerIds` | query | No | `string`[] | Partner identifiers. Repeated query params and comma-separated values are both accepted. | | `minReach` | query | No | `integer` | Minimum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `maxReach` | query | No | `integer` | Maximum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `cpm` | query | No | `number` | CPM used to convert spend filters into reach thresholds. | | `minSpend` | query | No | `number` | | | `maxSpend` | query | No | `number` | | | `spendPeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | query | No | `number` | | | `maxSpendPerPage` | query | No | `number` | | | `spendPerPagePeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `hideLowReach` | query | No | `boolean` | When true, hides ads flagged as low reach. | | `minAge` | query | No | `integer` | | | `maxAge` | query | No | `integer` | | | `sex` | query | No | `men` \| `women` \| `all` | Enum value accepted by this request. Allowed values: `men`, `women`, `all`. | | `minFacebookLikes` | query | No | `integer` | | | `maxFacebookLikes` | query | No | `integer` | | | `minInstagramFollowers` | query | No | `integer` | | | `maxInstagramFollowers` | query | No | `integer` | | | `minVideoDuration` | query | No | `number` | | | `maxVideoDuration` | query | No | `number` | | | `minDescriptionLength` | query | No | `integer` | | | `maxDescriptionLength` | query | No | `integer` | | | `linkedDomain` | query | No | `string` | Linked domain filter. URLs are normalized to their hostname before validation. | | `growthRank` | query | No | `rising` \| `falling` \| `stable`[] | Rank trend filters. Repeated query params and comma-separated values are both accepted. | | `snapshotDate` | query | No | `string` | Snapshot date (YYYY-MM-DD or latest). When present, status is interpreted as active at this date. | | `partnerId` | query | No | `string` | Single partner identifier alias. It is merged with partnerIds when both are provided. | ## Responses ### 200 - Brandtracker partnership ads count response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `count` | `number` | Yes | Deduped public ad groups matching the partnership ads list filters. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-hooks # Get brandtracker hooks `GET /v1/brandtrackers/{brandtrackerId}/hooks` Returns grouped hook analytics for the requested brandtracker using the authenticated workspace as the only access scope. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `usageCount` \| `longestRunning` \| `totalImpressions` \| `firstUsedAt` \| `lastUsedAt` | Optional hook sorting. Defaults to usageCount. | ## Responses ### 200 - Paginated brandtracker hooks analytics response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `hook` | `string` | Yes | | | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | | `totalImpressions` | `number` | Yes | Total impressions/reach contributed by ads using this hook. This aligns with Meta Ad Library reach vocabulary used elsewhere in the ads API. | | `firstUsedAt` | `string` | Yes | | | `lastUsedAt` | `string` | Yes | | | `sampleAd` | `object` | Yes | | **`sampleAd` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adId` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `fullText` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-transcripts # Get brandtracker transcripts `GET /v1/brandtrackers/{brandtrackerId}/transcripts` Returns grouped transcript/script analytics for the requested brandtracker using the authenticated workspace as the only access scope. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `usageCount` \| `longestRunning` \| `totalImpressions` \| `firstUsedAt` \| `lastUsedAt` | Optional transcript sorting. Defaults to usageCount. | ## Responses ### 200 - Paginated brandtracker transcripts analytics response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `fullText` | `string` | Yes | | | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | | `totalImpressions` | `number` | Yes | Total impressions/reach contributed by ads using this transcript. This aligns with Meta Ad Library reach vocabulary used elsewhere in the ads API. | | `firstUsedAt` | `string` | Yes | | | `lastUsedAt` | `string` | Yes | | | `sampleAd` | `object` | Yes | | **`sampleAd` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adId` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-headlines # Get brandtracker headlines `GET /v1/brandtrackers/{brandtrackerId}/headlines` Returns grouped headline analytics for the requested brandtracker. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `usageCount` \| `longestRunning` | Optional headline sorting. Defaults to usageCount. | ## Responses ### 200 - Paginated brandtracker headlines analytics response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `headline` | `string` | Yes | | | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-ad-copies # Get brandtracker ad copies `GET /v1/brandtrackers/{brandtrackerId}/ad-copies` Returns grouped ad copy analytics for the requested brandtracker. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `usageCount` \| `longestRunning` | Optional ad copy sorting. Defaults to usageCount. | ## Responses ### 200 - Paginated brandtracker ad copies analytics response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adCopy` | `string` | Yes | | | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-landing-pages # Get brandtracker landing pages `GET /v1/brandtrackers/{brandtrackerId}/landing-pages` Returns grouped landing page analytics for the requested brandtracker, including detected technologies when available. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `usageCount` \| `longestRunning` \| `totalImpressions` | Optional landing page sorting. Defaults to usageCount. | ## Responses ### 200 - Paginated brandtracker landing pages analytics response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `landingPage` | `string` | Yes | | | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | | `totalImpressions` | `number` | Yes | Total impressions/reach contributed by ads pointing to this landing page. This aligns with Meta Ad Library reach vocabulary used elsewhere in the ads API. | | `technologies` | `object`[] | Yes | | | `screenshots` | `object` | Yes | Best-effort landing page screenshot preview URLs from the screenshots table. | **`technologies[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `iconUrl` | `string` | Yes | | **`screenshots` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `desktop` | `object` | Yes | Latest desktop/full-page screenshot URL when available. | | `mobile` | `object` | Yes | Latest mobile screenshot URL when available. | | `head` | `object` | Yes | Latest above-the-fold/head screenshot URL when available. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-normalized-brandtracker-landing-pages # Get normalized brandtracker landing pages `GET /v1/brandtrackers/{brandtrackerId}/landing-pages/simple` Returns normalized/grouped landing page analytics for the requested brandtracker. Query strings, fragments, trailing slashes, and leading www. hostnames are ignored for grouping. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `usageCount` \| `activeAdsCount` | Optional normalized landing page sorting. Defaults to usageCount. | ## Responses ### 200 - Paginated normalized brandtracker landing pages analytics response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `landingPage` | `string` | Yes | Representative landing page URL with query string, fragment, and trailing slash removed. | | `normalizedLandingPage` | `string` | Yes | Normalized grouping key. Hostname is lowercased and leading www. is removed; query strings and fragments are ignored. | | `usageCount` | `number` | Yes | | | `activeAdsCount` | `number` | Yes | Number of currently active ads in this group for rolling windows. For live and snapshot queries this matches usageCount. | | `technologies` | `object`[] | Yes | | | `screenshots` | `object` | Yes | Best-effort landing page screenshot preview URLs from the screenshots table. | **`technologies[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `iconUrl` | `string` | Yes | | **`screenshots` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `desktop` | `object` | Yes | Latest desktop/full-page screenshot URL when available. | | `mobile` | `object` | Yes | Latest mobile screenshot URL when available. | | `head` | `object` | Yes | Latest above-the-fold/head screenshot URL when available. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-creatives # Get brandtracker creatives `GET /v1/brandtrackers/{brandtrackerId}/creatives` Returns paginated creative analytics for the requested brandtracker. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Time and snapshots: `timePeriod`, `snapshotDate` - Sorting: `order`, `sortBy` - Filters: `euOnly`, `mediaType` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `firstSeenAt` \| `daysRunning` \| `duplicates` | Optional creatives sorting. Defaults to firstSeenAt. | | `mediaType` | query | No | `all` \| `image` \| `video` | Optional media type filter. Defaults to all. | ## Responses ### 200 - Paginated brandtracker creatives response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adId` | `string` | Yes | | | `mediaType` | `image` \| `video` \| `unknown` | Yes | | | `mediaUrl` | `string` | Yes | | | `thumbnailUrl` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | | | `daysRunning` | `number` | Yes | | | `duplicates` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-partners # Get brandtracker partners `GET /v1/brandtrackers/{brandtrackerId}/partners` Returns paginated partnership analytics for the requested brandtracker. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Time and snapshots: `timePeriod`, `snapshotDate` - Sorting: `order`, `sortBy` - Filters: `euOnly`, `cpm` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Relative insights time window. Use stable windows like last7d or last30d for consistent agent behavior. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | Optional sort order. Defaults to desc. | | `snapshotDate` | query | No | `string` | Optional snapshot anchor date (YYYY-MM-DD). When provided, the requested window is evaluated against that snapshot date. | | `sortBy` | query | No | `activeAds` \| `launchDate` \| `reach` \| `estimatedSpend` | Optional partners sorting. Defaults to activeAds. | | `cpm` | query | No | `number` | Optional CPM used to estimate spend from reach. Defaults to 9. | ## Responses ### 200 - Paginated brandtracker partners response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `facebookPageId` | `string` | Yes | | | `name` | `string` | Yes | | | `activeAds` | `number` | Yes | | | `launchDate` | `string` | Yes | | | `reach` | `number` | Yes | Partner ad reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `estimatedSpend` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-media-mix # Get brandtracker media mix `GET /v1/brandtrackers/{brandtrackerId}/media-mix` Returns the media-format breakdown (image, video, dco, other) for the brandtracker's deduped currently active ads, or a deduped snapshot reconstruction when a snapshotDate is provided. activeAds equals the sum of the media buckets. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `snapshotDate` | query | No | `string` | Optional snapshot date (YYYY-MM-DD or latest). When provided, the mix is reconstructed for that date; otherwise it uses live active ads. Counts are deduped by ad before media buckets are calculated. | ## Responses ### 200 - Brandtracker media mix response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `meta` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | Number of deduped eligible ads in the media mix. Equals image + video + dco + other. | | `formatCount` | `object` | Yes | Media-format buckets counted from the same deduped eligible-ad set as activeAds. Carousel is not exposed as a separate media-mix bucket; carousel creatives are currently folded into image, video, dco, or other based on the indexed media format. | **`formatCount` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `image` | `number` | Yes | | | `video` | `number` | Yes | | | `dco` | `number` | Yes | | | `other` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-demography # Get brandtracker demography `GET /v1/brandtrackers/{brandtrackerId}/demography` Returns the EU country / age / gender reach distributions precomputed for the brandtracker. The underlying dataset is page-level and EU-only, so this endpoint is fundamentally EU-scoped. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `euOnly` | query | No | `boolean` | EU-only filter. This endpoint is fundamentally EU-scoped (the source data is the EU-only fb_page_reach_by_country table), so this defaults to true and is retained for forward compatibility. | | `snapshotDate` | query | No | `string` | Optional snapshot date (YYYY-MM-DD or latest). The underlying demography data is currently a precomputed per-page snapshot (not time-windowed), so this parameter is accepted for forward compatibility but does not filter the result today. | | `timePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Optional time window. The underlying demography data is currently a precomputed per-page snapshot (not time-windowed), so this parameter is accepted for forward compatibility but does not filter the result today. | ## Responses ### 200 - Brandtracker demography distributions response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `hasData` | `boolean` | Yes | | | `countryDistribution` | `object`[] | Yes | | | `ageDistribution` | `object`[] | Yes | | | `genderDistribution` | `object`[] | Yes | | **`countryDistribution[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `countryCode` | `string` | Yes | | | `reach` | `number` | Yes | Reach attributed to this country. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | **`ageDistribution[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `ageRange` | `string` | Yes | | | `reach` | `number` | Yes | Reach attributed to this age range. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | **`genderDistribution[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `gender` | `female` \| `male` \| `unknown` | Yes | | | `reach` | `number` | Yes | Reach attributed to this gender bucket. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-current-ranked-top-ads # Get current ranked top ads `GET /v1/brandtrackers/{brandtrackerId}/top-ads` Canonical current-ranking endpoint for a brandtracker. Use sortBy=currentRank for the current Facebook page rank, sortBy=reach/reachDelta1d/reachDelta7d/reachDelta30d for reach rankings, and sortBy=rankDelta7d/rankDelta14d/rankDelta30d for rank movers. period and snapshotDate are deprecated compatibility parameters and are ignored on this current-ranking path. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Time and snapshots: `period`, `snapshotDate` - Sorting: `sortBy` - Filters: `facebookPageId`, `allFacebookPages`, `euOnly`, `status`, `includeInactive` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `facebookPageId` | query | No | `string` | Optional Facebook page id belonging to this brandtracker. When omitted, the primary Facebook page is used. | | `allFacebookPages` | query | No | `boolean` | When true, aggregate all selected Facebook pages. Current ranks are page-local, so ties across pages are expected. Cannot be combined with facebookPageId. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `sortBy` | query | No | `currentRank` \| `rankDelta` \| `rankDelta7d` \| `rankDelta14d` \| `rankDelta30d` \| `reach` \| `reachDelta1d` \| `reachDelta7d` \| `reachDelta30d` \| `daysRunning` \| `duplicates` | Sort key for canonical current rankings. Use currentRank for the selected Facebook page rank (returned as rank/currentRank); rankDelta7d, rankDelta14d, or rankDelta30d for movers; reach, reachDelta1d, reachDelta7d, or reachDelta30d for reach rankings. | | `status` | query | No | `active` \| `inactive` \| `all` | Preferred activity filter. active returns active ads, inactive returns inactive ads, all returns both. When supplied, it takes precedence over includeInactive. | | `includeInactive` | query | No | `boolean` | Deprecated. When status is omitted, includeInactive=true maps to status=all; ignored when status is supplied. | | `period` | query | No | `today` \| `yesterday` \| `last1d` \| `last7d` \| `last14d` \| `last30d` \| `total` | Optional rolling top-ads period. Allowed values: today, yesterday, last1d, last7d, last14d, last30d, total. | | `snapshotDate` | query | No | `object` | Deprecated compatibility parameter accepted but ignored by canonical top-ads current ranking. Use freshness/system endpoints for snapshot availability checks. | ## Responses ### 200 - Paginated brandtracker top ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | No | Optional empty-result diagnostics. Omitted on normal top-ads responses. | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `ad` | `object` | Yes | | | `metrics` | `object` | Yes | | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `totalReach` | `number` | Yes | Total reach for the ranked ad. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric; EU impressions/reach are used where available. | | `duplicateCount` | `number` | Yes | | | `daysRunning` | `number` | Yes | | | `currentRank` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reason` | `no_snapshot_for_period` \| `no_reach_history_for_period` \| `no_matching_ads` | No | Present on empty result sets to distinguish filters with no matching ads. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-ad-rank-compatibility-data # Get brandtracker ad rank compatibility data `GET /v1/brandtrackers/{brandtrackerId}/ad-rank` Compatibility endpoint for clients that still call /ad-rank. Prefer /v1/brandtrackers/{brandtrackerId}/top-ads?sortBy=rankDelta7d, rankDelta14d, or rankDelta30d for canonical rank movers and sortBy=currentRank for current ranking. Endpoint key, billing, and response envelope remain stable; snapshotDate is deprecated and ignored on the ES-backed path, and trajectory may be empty. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `timeWindow` | query | No | `last7d` \| `last14d` \| `last30d` \| `7d` \| `14d` \| `30d` | Scaling comparison window. Prefer stable windows (last7d or last14d) for agent workflows. | | `sortBy` | query | No | `rankDelta` \| `currentRank` \| `rank_delta` \| `current_rank` | Optional scaling ads sort key. Defaults to rankDelta. Also accepts legacy aliases rank_delta and current_rank. | | `snapshotDate` | query | No | `string` | Deprecated compatibility parameter accepted but ignored on the ES-backed compatibility path. Use top-ads sortBy=rankDelta7d/14d/30d for canonical rank movers. | | `maxCurrentRank` | query | No | `integer` | Optional maximum current rank filter. Only ads at or above this current rank are returned. | | `minRankDelta` | query | No | `integer` | Minimum positive rank improvement required for an ad to be returned. Defaults to 1. | ## Responses ### 200 - Paginated brandtracker ad rank response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `ad` | `object` | Yes | | | `metrics` | `object` | Yes | | | `trajectory` | `object`[] | Yes | Daily rank trajectory for this ad over the selected comparison window. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currentRank` | `number` | Yes | | | `previousRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | Positive rank improvement over the selected comparison window. | | `improvementPct` | `object` | Yes | Percentage improvement from previousRank to currentRank over the selected comparison window. | **`trajectory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | Trajectory point date in YYYY-MM-DD format. | | `rank` | `number` | Yes | | | `totalAds` | `object` | Yes | Estimated total ranked ads for this snapshot when available. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-scaling-ads-compatibility-data # Get brandtracker scaling ads compatibility data `GET /v1/brandtrackers/{brandtrackerId}/scaling-ads` Legacy compatibility endpoint for clients that still call /scaling-ads. Prefer /v1/brandtrackers/{brandtrackerId}/top-ads?sortBy=rankDelta7d, rankDelta14d, or rankDelta30d for canonical rank movers and sortBy=currentRank for current ranking. Endpoint key, billing, and response envelope remain stable; snapshotDate is deprecated and ignored on the ES-backed path, and trajectory may be empty. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of items to return. Defaults to 20. | | `timeWindow` | query | No | `last7d` \| `last14d` \| `last30d` \| `7d` \| `14d` \| `30d` | Scaling comparison window. Prefer stable windows (last7d or last14d) for agent workflows. | | `sortBy` | query | No | `rankDelta` \| `currentRank` \| `rank_delta` \| `current_rank` | Optional scaling ads sort key. Defaults to rankDelta. Also accepts legacy aliases rank_delta and current_rank. | | `snapshotDate` | query | No | `string` | Deprecated compatibility parameter accepted but ignored on the ES-backed compatibility path. Use top-ads sortBy=rankDelta7d/14d/30d for canonical rank movers. | | `maxCurrentRank` | query | No | `integer` | Optional maximum current rank filter. Only ads at or above this current rank are returned. | | `minRankDelta` | query | No | `integer` | Minimum positive rank improvement required for an ad to be returned. Defaults to 1. | ## Responses ### 200 - Paginated brandtracker scaling ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `ad` | `object` | Yes | | | `metrics` | `object` | Yes | | | `trajectory` | `object`[] | Yes | Daily rank trajectory for this ad over the selected comparison window. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currentRank` | `number` | Yes | | | `previousRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | Positive rank improvement over the selected comparison window. | | `improvementPct` | `object` | Yes | Percentage improvement from previousRank to currentRank over the selected comparison window. | **`trajectory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | Trajectory point date in YYYY-MM-DD format. | | `rank` | `number` | Yes | | | `totalAds` | `object` | Yes | Estimated total ranked ads for this snapshot when available. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-overview # Get brandtracker overview `GET /v1/brandtrackers/{brandtrackerId}/overview` Returns a dashboard-style Brandtracker overview combining graph, media mix, top landing pages, top ads, and ads preview sections. The graph accepts timeSeriesPeriod for rolling windows or timeSeriesStartDate/timeSeriesEndDate for explicit ranges; do not combine them. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Time and snapshots: `snapshotDate`, `timeSeriesStartDate`, `timeSeriesEndDate`, `timeSeriesPeriod`, `landingPagesTimePeriod`, `topAdsPeriod` - Sorting: `topAdsSortBy` - Filters: `euOnly`, `cpm`, `timeSeriesGranularity`, `landingPagesLimit`, `topAdsLimit`, `adsPreviewLimit` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `euOnly` | query | No | `boolean` | Optional EU-only filter forwarded to graph, media mix, landing pages, and top ads sections where supported. | | `snapshotDate` | query | No | `object` | Snapshot date for dashboard time travel. Use YYYY-MM-DD or latest. | | `cpm` | query | No | `number` | CPM used to estimate spend in the graph section. | | `timeSeriesGranularity` | query | No | `daily` \| `weekly` \| `monthly` | Bucket size for the graph section. Defaults to daily. | | `timeSeriesStartDate` | query | No | `string` | Inclusive graph start date. Cannot be combined with timeSeriesPeriod. | | `timeSeriesEndDate` | query | No | `string` | Inclusive graph end date. Cannot be combined with timeSeriesPeriod. | | `timeSeriesPeriod` | query | No | `today` \| `yesterday` \| `1d` \| `7d` \| `14d` \| `30d` \| `90d` \| `365d` | Optional rolling window for the graph section. Supports today, yesterday, 1d, 7d, 14d, 30d, 90d, and 365d. Cannot be combined with timeSeriesStartDate or timeSeriesEndDate; snapshotDate may anchor the window. | | `landingPagesTimePeriod` | query | No | `live` \| `last24h` \| `last3d` \| `last7d` \| `last30d` \| `last3m` \| `last6m` \| `last1y` | Time window for top landing pages. Defaults to live for dashboard-style current overview. | | `landingPagesLimit` | query | No | `integer` | Maximum number of top landing pages to return. Defaults to 5. | | `topAdsLimit` | query | No | `integer` | Maximum number of top ads to return. Defaults to 5. | | `adsPreviewLimit` | query | No | `integer` | Maximum number of ads preview items to return. Defaults to 10. | | `topAdsSortBy` | query | No | `currentRank` \| `rankDelta` \| `rankDelta7d` \| `rankDelta14d` \| `rankDelta30d` \| `reach` \| `reachDelta1d` \| `reachDelta7d` \| `reachDelta30d` \| `daysRunning` \| `duplicates` | Optional top ads sorting. Defaults to reach when euOnly=true, otherwise daysRunning. | | `topAdsPeriod` | query | No | `today` \| `yesterday` \| `last1d` \| `last7d` \| `last14d` \| `last30d` \| `total` | Optional top ads period. Supports `today`, `yesterday`, `last1d`, `last7d`, `last14d`, `last30d`, and `total`. Defaults to `total`. | ## Responses ### 200 - Brandtracker overview response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `meta` | `object` | Yes | Reserved response metadata. Snapshot freshness is intentionally omitted from overview to match top-ads. | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `graph` | `object` | Yes | | | `mediaMix` | `object` | Yes | | | `topLandingPages` | `object` | Yes | | | `topAds` | `object` | Yes | | | `adsPreview` | `object` | Yes | | **`graph` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `granularity` | `daily` \| `weekly` \| `monthly` | Yes | | | `dateRange` | `object` | Yes | | | `adsLaunched` | `object`[] | Yes | | | `liveAds` | `object`[] | Yes | | | `euImpressionsSpend` | `object`[] | Yes | EU impressions/reach spend time series. For Meta Ad Library data, reach is the public-facing impressions-style vocabulary used by related ad DTOs. | | `cpm` | `number` | Yes | | **`dateRange` properties:** **`adsLaunched[]` item properties:** **`liveAds[]` item properties:** **`euImpressionsSpend[]` item properties:** **`mediaMix` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | Number of deduped eligible ads in the media mix. Equals image + video + dco + other. | | `formatCount` | `object` | Yes | Media-format buckets counted from the same deduped eligible-ad set as activeAds. Carousel is not exposed as a separate media-mix bucket; carousel creatives are currently folded into image, video, dco, or other based on the indexed media format. | **`formatCount` properties:** **`topLandingPages` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** **`pagination` properties:** **`topAds` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** **`pagination` properties:** **`adsPreview` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** **`pagination` properties:** --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtracker-timeline-ads # List brandtracker timeline ads `GET /v1/brandtrackers/{brandtrackerId}/timeline` Returns timeline-ready Meta ads for one active workspace brandtracker resolved from brandtracker.id. Timeline membership includes non-deleted Facebook ads with media available in the bucket and a non-null start date. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `keywordMode` - Time and snapshots: `createdAfter`, `createdBefore`, `spendPeriod`, `spendPerPagePeriod`, `snapshotDate` - Sorting: `sortBy` - Filters: `status`, `mediaType`, `keywords`, `minDaysRunning`, `maxDaysRunning`, `minDuplicates`, `maxDuplicates`, `landingPages`, `adLanguage`, `cta`, `adCopyHashes`, `adCountries`, `mainCountries`, `euOnly`, `partners`, `partnerIds`, `minReach`, `maxReach`, `cpm`, `minSpend`, `maxSpend`, `minSpendPerPage`, `maxSpendPerPage`, `hideLowReach`, `minAge`, `maxAge`, `sex`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minVideoDuration`, `maxVideoDuration`, `minDescriptionLength`, `maxDescriptionLength`, `linkedDomain`, `growthRank`, `startedAfter`, `startedBefore`, `lastSeenAfter`, `lastSeenBefore` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `sortBy` | query | No | `newest` \| `createdAt` \| `longestRunning` \| `reach` \| `duplicates` \| `adOrder` \| `relevance` | Sort key for this request. Allowed values: `newest`, `createdAt`, `longestRunning`, `reach`, `duplicates`, `adOrder`, `relevance`. | | `status` | query | No | `all` \| `active` \| `inactive` | Status filter for this request. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Enum value accepted by this request. Allowed values: `all`, `image`, `video`. | | `keywords` | query | No | `string`[] | Keyword search terms. Repeated query params and comma-separated values are both accepted. | | `keywordMode` | query | No | `any` \| `all` | Enum value accepted by this request. Allowed values: `any`, `all`. | | `createdAfter` | query | No | `string` | | | `createdBefore` | query | No | `string` | | | `minDaysRunning` | query | No | `integer` | | | `maxDaysRunning` | query | No | `integer` | | | `minDuplicates` | query | No | `integer` | | | `maxDuplicates` | query | No | `integer` | | | `landingPages` | query | No | `string`[] | Landing page URLs. Repeated query params and comma-separated values are both accepted. | | `adLanguage` | query | No | `string`[] | Ad languages. Repeated query params and comma-separated values are both accepted. | | `cta` | query | No | `string`[] | Call-to-action labels. Repeated query params and comma-separated values are both accepted. | | `adCopyHashes` | query | No | `string`[] | 12-character MD5 prefixes of ad copy descriptions. Repeated query params and comma-separated values are both accepted. | | `adCountries` | query | No | `string` | Ad country include/exclude filter. Use comma-separated ISO codes with include/exclude modes. | | `mainCountries` | query | No | `string`[] | Main ad countries. Repeated query params and comma-separated values are both accepted. | | `euOnly` | query | No | `boolean` | When true, keep only ads flagged as EU ads. | | `partners` | query | No | `boolean` | When true, keep only partnership ads. When false, keep only non-partnership ads. | | `partnerIds` | query | No | `string`[] | Partner identifiers. Repeated query params and comma-separated values are both accepted. | | `minReach` | query | No | `integer` | Minimum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `maxReach` | query | No | `integer` | Maximum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `cpm` | query | No | `number` | CPM used to convert spend filters into reach thresholds. | | `minSpend` | query | No | `number` | | | `maxSpend` | query | No | `number` | | | `spendPeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | query | No | `number` | | | `maxSpendPerPage` | query | No | `number` | | | `spendPerPagePeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `hideLowReach` | query | No | `boolean` | When true, hides ads flagged as low reach. | | `minAge` | query | No | `integer` | | | `maxAge` | query | No | `integer` | | | `sex` | query | No | `men` \| `women` \| `all` | Enum value accepted by this request. Allowed values: `men`, `women`, `all`. | | `minFacebookLikes` | query | No | `integer` | | | `maxFacebookLikes` | query | No | `integer` | | | `minInstagramFollowers` | query | No | `integer` | | | `maxInstagramFollowers` | query | No | `integer` | | | `minVideoDuration` | query | No | `number` | | | `maxVideoDuration` | query | No | `number` | | | `minDescriptionLength` | query | No | `integer` | | | `maxDescriptionLength` | query | No | `integer` | | | `linkedDomain` | query | No | `string` | Linked domain filter. URLs are normalized to their hostname before validation. | | `growthRank` | query | No | `rising` \| `falling` \| `stable`[] | Rank trend filters. Repeated query params and comma-separated values are both accepted. | | `snapshotDate` | query | No | `string` | Snapshot date (YYYY-MM-DD or latest). When present, status is interpreted as active at this date. | | `startedAfter` | query | No | `string` | Inclusive ad start-date lower bound. | | `startedBefore` | query | No | `string` | Inclusive ad start-date upper bound. | | `lastSeenAfter` | query | No | `string` | Inclusive effective timeline end-date lower bound. Active ads use today, or snapshotDate when provided. | | `lastSeenBefore` | query | No | `string` | Inclusive effective timeline end-date upper bound. Active ads use today, or snapshotDate when provided. | ## Responses ### 200 - Paginated brandtracker timeline response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `type` | `image` \| `video` \| `carousel` \| `unknown` | Yes | Creative media type from indexed ad data. `carousel` means carousel creative format and is not a DCO signal. | | `thumbnailUrl` | `string` | Yes | | | `mediaUrl` | `string` | Yes | | **`advertiser` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `logoUrl` | `string` | Yes | | | `facebookPageId` | `string` | Yes | | | `liveAdsCount` | `number` | Yes | | | `reach30d` | `number` | Yes | Advertiser reach for the last 30 days. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `totalReach` | `number` | Yes | Advertiser total/current reach. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `countriesCount` | `number` | Yes | | | `facebookLikes` | `number` | Yes | | | `instagramFollowers` | `number` | Yes | | **`content` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `title` | `string` | Yes | | | `body` | `string` | Yes | | | `transcript` | `string` | Yes | Backward-compatible plain transcript text. Rich transcript metadata may also be available on detail responses. | | `callToAction` | `string` | Yes | | | `landingPageUrl` | `string` | Yes | | | `landingPageDomain` | `string` | Yes | | | `ctaDescription` | `string` | Yes | | | `ctaLinkDescription` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `number` | Yes | Ad reach where available. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric. | | `aggregatedReach` | `number` | Yes | Aggregated ad reach across duplicates where available; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `estimatedSpend` | `number` | Yes | Estimated spend in euros. Formula: reach * cpm / 1000, using the request cpm or the default CPM of 9 when cpm is omitted. Rounded to the nearest integer. | | `duplicates` | `number` | Yes | | | `reachDelta1d` | `number` | Yes | One-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta7d` | `number` | Yes | Seven-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | | `reachDelta30d` | `number` | Yes | Thirty-day reach delta; reach corresponds to the public impressions-style metric from Meta Ad Library data. | **`audience` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetedCountries` | `string`[] | Yes | Full ad targeting country list, including non-EU markets such as US. | | `mainCountry` | `string` | Yes | Primary audience country from Meta's EU/UK ad transparency reporting. Null for ads outside that scope, even when targetedCountries is populated. | | `gender` | `men` \| `women` \| `all` | Yes | | | `ageMin` | `number` | Yes | | | `ageMax` | `number` | Yes | | **`rank` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `positionInPage` | `number` | Yes | | | `currentRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | | | `improvementPct` | `number` | Yes | | **`flags` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `isEuAd` | `boolean` | Yes | | | `isLowReach` | `boolean` | Yes | Whether the ad is flagged as low reach/low impressions in the indexed Meta Ad Library data. | | `isMediaChanged` | `boolean` | Yes | | | `hasPartnerBadge` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-timeline-metadata # Get brandtracker timeline metadata `GET /v1/brandtrackers/{brandtrackerId}/timeline/metadata` Returns total count and date bounds for the same filter membership used by the brandtracker timeline endpoint. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Search: `keywordMode` - Time and snapshots: `createdAfter`, `createdBefore`, `spendPeriod`, `spendPerPagePeriod`, `snapshotDate` - Filters: `status`, `mediaType`, `keywords`, `minDaysRunning`, `maxDaysRunning`, `minDuplicates`, `maxDuplicates`, `landingPages`, `adLanguage`, `cta`, `adCopyHashes`, `adCountries`, `mainCountries`, `euOnly`, `partners`, `partnerIds`, `minReach`, `maxReach`, `cpm`, `minSpend`, `maxSpend`, `minSpendPerPage`, `maxSpendPerPage`, `hideLowReach`, `minAge`, `maxAge`, `sex`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minVideoDuration`, `maxVideoDuration`, `minDescriptionLength`, `maxDescriptionLength`, `linkedDomain`, `growthRank`, `startedAfter`, `startedBefore`, `lastSeenAfter`, `lastSeenBefore` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `status` | query | No | `all` \| `active` \| `inactive` | Status filter for this request. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Enum value accepted by this request. Allowed values: `all`, `image`, `video`. | | `keywords` | query | No | `string`[] | Keyword search terms. Repeated query params and comma-separated values are both accepted. | | `keywordMode` | query | No | `any` \| `all` | Enum value accepted by this request. Allowed values: `any`, `all`. | | `createdAfter` | query | No | `string` | | | `createdBefore` | query | No | `string` | | | `minDaysRunning` | query | No | `integer` | | | `maxDaysRunning` | query | No | `integer` | | | `minDuplicates` | query | No | `integer` | | | `maxDuplicates` | query | No | `integer` | | | `landingPages` | query | No | `string`[] | Landing page URLs. Repeated query params and comma-separated values are both accepted. | | `adLanguage` | query | No | `string`[] | Ad languages. Repeated query params and comma-separated values are both accepted. | | `cta` | query | No | `string`[] | Call-to-action labels. Repeated query params and comma-separated values are both accepted. | | `adCopyHashes` | query | No | `string`[] | 12-character MD5 prefixes of ad copy descriptions. Repeated query params and comma-separated values are both accepted. | | `adCountries` | query | No | `string` | Ad country include/exclude filter. Use comma-separated ISO codes with include/exclude modes. | | `mainCountries` | query | No | `string`[] | Main ad countries. Repeated query params and comma-separated values are both accepted. | | `euOnly` | query | No | `boolean` | When true, keep only ads flagged as EU ads. | | `partners` | query | No | `boolean` | When true, keep only partnership ads. When false, keep only non-partnership ads. | | `partnerIds` | query | No | `string`[] | Partner identifiers. Repeated query params and comma-separated values are both accepted. | | `minReach` | query | No | `integer` | Minimum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `maxReach` | query | No | `integer` | Maximum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `cpm` | query | No | `number` | CPM used to convert spend filters into reach thresholds. | | `minSpend` | query | No | `number` | | | `maxSpend` | query | No | `number` | | | `spendPeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | query | No | `number` | | | `maxSpendPerPage` | query | No | `number` | | | `spendPerPagePeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `hideLowReach` | query | No | `boolean` | When true, hides ads flagged as low reach. | | `minAge` | query | No | `integer` | | | `maxAge` | query | No | `integer` | | | `sex` | query | No | `men` \| `women` \| `all` | Enum value accepted by this request. Allowed values: `men`, `women`, `all`. | | `minFacebookLikes` | query | No | `integer` | | | `maxFacebookLikes` | query | No | `integer` | | | `minInstagramFollowers` | query | No | `integer` | | | `maxInstagramFollowers` | query | No | `integer` | | | `minVideoDuration` | query | No | `number` | | | `maxVideoDuration` | query | No | `number` | | | `minDescriptionLength` | query | No | `integer` | | | `maxDescriptionLength` | query | No | `integer` | | | `linkedDomain` | query | No | `string` | Linked domain filter. URLs are normalized to their hostname before validation. | | `growthRank` | query | No | `rising` \| `falling` \| `stable`[] | Rank trend filters. Repeated query params and comma-separated values are both accepted. | | `snapshotDate` | query | No | `string` | Snapshot date (YYYY-MM-DD or latest). When present, status is interpreted as active at this date. | | `startedAfter` | query | No | `string` | Inclusive ad start-date lower bound. | | `startedBefore` | query | No | `string` | Inclusive ad start-date upper bound. | | `lastSeenAfter` | query | No | `string` | Inclusive effective timeline end-date lower bound. Active ads use today, or snapshotDate when provided. | | `lastSeenBefore` | query | No | `string` | Inclusive effective timeline end-date upper bound. Active ads use today, or snapshotDate when provided. | ## Responses ### 200 - Brandtracker timeline metadata response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `totalCount` | `number` | Yes | | | `earliestDate` | `string` | Yes | | | `latestDate` | `string` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#list-brandtracker-creative-testing-batches # List brandtracker creative testing batches `GET /v1/brandtrackers/{brandtrackerId}/testing` Returns creative-testing batches grouped by ad start date for one active workspace brandtracker resolved from brandtracker.id. Testing membership includes non-deleted Facebook ads with media available in the bucket and a non-null start date. To keep response size and metering bounded, each batch returns at most 20 ads and exposes truncation metadata. **Tags:** Brandtrackers ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Search: `keywordMode` - Time and snapshots: `createdAfter`, `createdBefore`, `spendPeriod`, `spendPerPagePeriod`, `snapshotDate` - Filters: `status`, `mediaType`, `keywords`, `minDaysRunning`, `maxDaysRunning`, `minDuplicates`, `maxDuplicates`, `landingPages`, `adLanguage`, `cta`, `adCopyHashes`, `adCountries`, `mainCountries`, `euOnly`, `partners`, `partnerIds`, `minReach`, `maxReach`, `cpm`, `minSpend`, `maxSpend`, `minSpendPerPage`, `maxSpendPerPage`, `hideLowReach`, `minAge`, `maxAge`, `sex`, `minFacebookLikes`, `maxFacebookLikes`, `minInstagramFollowers`, `maxInstagramFollowers`, `minVideoDuration`, `maxVideoDuration`, `minDescriptionLength`, `maxDescriptionLength`, `linkedDomain`, `growthRank`, `startedAfter`, `startedBefore`, `lastSeenAfter`, `lastSeenBefore` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Batch page number. Pagination is by distinct ad start-date batches. | | `limit` | query | No | `integer` | Number of distinct start-date batches to return. Each batch returns at most 20 ads. | | `status` | query | No | `all` \| `active` \| `inactive` | Status filter for this request. Allowed values: `all`, `active`, `inactive`. | | `mediaType` | query | No | `all` \| `image` \| `video` | Enum value accepted by this request. Allowed values: `all`, `image`, `video`. | | `keywords` | query | No | `string`[] | Keyword search terms. Repeated query params and comma-separated values are both accepted. | | `keywordMode` | query | No | `any` \| `all` | Enum value accepted by this request. Allowed values: `any`, `all`. | | `createdAfter` | query | No | `string` | | | `createdBefore` | query | No | `string` | | | `minDaysRunning` | query | No | `number` | | | `maxDaysRunning` | query | No | `number` | | | `minDuplicates` | query | No | `number` | | | `maxDuplicates` | query | No | `number` | | | `landingPages` | query | No | `string`[] | Landing page URLs. Repeated query params and comma-separated values are both accepted. | | `adLanguage` | query | No | `string`[] | Ad languages. Repeated query params and comma-separated values are both accepted. | | `cta` | query | No | `string`[] | Call-to-action labels. Repeated query params and comma-separated values are both accepted. | | `adCopyHashes` | query | No | `string`[] | 12-character MD5 prefixes of ad copy descriptions. Repeated query params and comma-separated values are both accepted. | | `adCountries` | query | No | `string` | Ad country include/exclude filter. Use comma-separated ISO codes with include/exclude modes. | | `mainCountries` | query | No | `string`[] | Main ad countries. Repeated query params and comma-separated values are both accepted. | | `euOnly` | query | No | `boolean` | When true, keep only ads flagged as EU ads. | | `partners` | query | No | `boolean` | When true, keep only partnership ads. When false, keep only non-partnership ads. | | `partnerIds` | query | No | `string`[] | Partner identifiers. Repeated query params and comma-separated values are both accepted. | | `minReach` | query | No | `number` | Minimum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `maxReach` | query | No | `number` | Maximum ad reach threshold. Backed by the internal reach/impressions analytics field. | | `cpm` | query | No | `number` | CPM used to convert spend filters into reach thresholds. | | `minSpend` | query | No | `number` | | | `maxSpend` | query | No | `number` | | | `spendPeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `minSpendPerPage` | query | No | `number` | | | `maxSpendPerPage` | query | No | `number` | | | `spendPerPagePeriod` | query | No | `total` \| `last24h` \| `last7d` \| `last30d` | Enum value accepted by this request. Allowed values: `total`, `last24h`, `last7d`, `last30d`. | | `hideLowReach` | query | No | `boolean` | When true, hides ads flagged as low reach. | | `minAge` | query | No | `number` | | | `maxAge` | query | No | `number` | | | `sex` | query | No | `men` \| `women` \| `all` | Enum value accepted by this request. Allowed values: `men`, `women`, `all`. | | `minFacebookLikes` | query | No | `number` | | | `maxFacebookLikes` | query | No | `number` | | | `minInstagramFollowers` | query | No | `number` | | | `maxInstagramFollowers` | query | No | `number` | | | `minVideoDuration` | query | No | `number` | | | `maxVideoDuration` | query | No | `number` | | | `minDescriptionLength` | query | No | `number` | | | `maxDescriptionLength` | query | No | `number` | | | `linkedDomain` | query | No | `string` | Linked domain filter. URLs are normalized to their hostname before validation. | | `growthRank` | query | No | `rising` \| `falling` \| `stable`[] | Rank trend filters. Repeated query params and comma-separated values are both accepted. | | `snapshotDate` | query | No | `string` | Snapshot date (YYYY-MM-DD or latest). When present, status is interpreted as active at this date. | | `startedAfter` | query | No | `string` | Inclusive ad start-date lower bound. | | `startedBefore` | query | No | `string` | Inclusive ad start-date upper bound. | | `lastSeenAfter` | query | No | `string` | Inclusive effective timeline end-date lower bound. Active ads use today, or snapshotDate when provided. | | `lastSeenBefore` | query | No | `string` | Inclusive effective timeline end-date upper bound. Active ads use today, or snapshotDate when provided. | ## Responses ### 200 - Paginated brandtracker testing response. Pagination is by start-date batches and the response includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `startDate` | `string` | Yes | | | `ads` | `object`[] | Yes | | | `adsReturned` | `number` | Yes | Number of ads returned in this batch after the per-batch cap. | | `maxAdsPerBatch` | `number` | Yes | Maximum ads returned per start-date batch. | | `adsTruncated` | `boolean` | Yes | True when more matching ads exist for this start-date batch than were returned. | | `runningCount` | `number` | Yes | | | `isWinner` | `boolean` | Yes | True when the batch matches the creative-testing winner heuristics. | | `stats` | `object` | Yes | | **`ads[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`stats` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reach` | `object` | Yes | | | `daysRunning` | `object` | Yes | | | `activeCount` | `number` | Yes | | | `totalCount` | `number` | Yes | | | `bestPerformerId` | `string` | Yes | | **`reach` properties:** **`daysRunning` properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | Number of start-date batches requested per page. | | `total` | `number` | Yes | Total matching start-date batches. | | `totalPages` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-time-series # Get brandtracker time-series `GET /v1/brandtrackers/{brandtrackerId}/time-series` Returns graph-ready Brandtracker time-series for ads launched, live ads history, and EU impression/spend deltas. Use period for rolling windows, or startDate/endDate for explicit ranges; do not combine period with date params. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `granularity` | query | No | `daily` \| `weekly` \| `monthly` | Bucket size for the returned graph data. Defaults to daily. | | `startDate` | query | No | `string` | Inclusive start date. Defaults to 365 days before the effective end date. Cannot be combined with period. | | `endDate` | query | No | `string` | Inclusive end date. Defaults to today unless snapshotDate is provided. Cannot be combined with period. | | `snapshotDate` | query | No | `string` | Optional snapshot date. When provided with period, it anchors the rolling window; otherwise it is used as the effective end date. | | `period` | query | No | `today` \| `yesterday` \| `1d` \| `7d` \| `14d` \| `30d` \| `90d` \| `365d` | Optional rolling window for the time-series. Supports today, yesterday, 1d, 7d, 14d, 30d, 90d, and 365d. Cannot be combined with startDate or endDate; snapshotDate may anchor the window. | | `euOnly` | query | No | `boolean` | When true, only EU-classified ads are counted for adsLaunched. | | `cpm` | query | No | `number` | CPM used to estimate spend from EU impression deltas. | ## Responses ### 200 - Brandtracker time-series response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object` | Yes | | | `meta` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `granularity` | `daily` \| `weekly` \| `monthly` | Yes | | | `dateRange` | `object` | Yes | | | `adsLaunched` | `object`[] | Yes | | | `liveAds` | `object`[] | Yes | | | `euImpressionsSpend` | `object`[] | Yes | EU impressions/reach spend time series. For Meta Ad Library data, reach is the public-facing impressions-style vocabulary used by related ad DTOs. | | `cpm` | `number` | Yes | | **`dateRange` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `startDate` | `string` | Yes | | | `endDate` | `string` | Yes | | **`adsLaunched[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `count` | `number` | Yes | | **`liveAds[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `count` | `number` | Yes | | **`euImpressionsSpend[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `impressions` | `number` | Yes | Impression delta within this bucket. | | `cumulativeImpressions` | `number` | Yes | Latest cumulative EU impressions value observed in this bucket. | | `estimatedSpend` | `number` | Yes | Estimated spend for this bucket, computed from impressions and cpm. | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-ad-copy-evolution # Get brandtracker ad copy evolution `GET /v1/brandtrackers/{brandtrackerId}/ad-copy-evolution` Returns graph-ready ad copy evolution series for one active workspace brandtracker resolved from brandtracker.id. Provide adCopy for exact single-text mode, or omit it to page through bounded global series ranked by active ads. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number for global mode. Exact mode always returns at most one series. | | `limit` | query | No | `integer` | Number of series to return in global mode. Exact mode costs and returns one series. | | `startDate` | query | No | `string` | Inclusive start date. Defaults to 365 days before the effective end date. | | `endDate` | query | No | `string` | Inclusive end date. Defaults to today unless snapshotDate is provided. | | `snapshotDate` | query | No | `string` | Optional snapshot date. When provided, it is used as the effective end date. | | `adCopy` | query | No | `string` | Exact ad copy text to return as a single evolution series. Omit for global mode. | ## Responses ### 200 - Paginated ad copy evolution response. Pagination is by distinct ad copy series and the response includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `dateRange` | `object` | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`dateRange` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `startDate` | `string` | Yes | | | `endDate` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `adCopy` | `string` | Yes | | | `points` | `object`[] | Yes | | **`points[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `recordedAt` | `string` | Yes | Timestamp of the history snapshot used for this point. | | `activeAds` | `number` | Yes | | | `totalAds` | `number` | Yes | | | `euAds` | `number` | Yes | | | `euActiveAds` | `number` | Yes | | | `totalReach` | `number` | Yes | Total reach at this history point. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `percentNewAds` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-headline-evolution # Get brandtracker headline evolution `GET /v1/brandtrackers/{brandtrackerId}/headline-evolution` Returns graph-ready headline evolution series for one active workspace brandtracker resolved from brandtracker.id. Provide headline for exact single-text mode, or omit it to page through bounded global series ranked by active ads. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number for global mode. Exact mode always returns at most one series. | | `limit` | query | No | `integer` | Number of series to return in global mode. Exact mode costs and returns one series. | | `startDate` | query | No | `string` | Inclusive start date. Defaults to 365 days before the effective end date. | | `endDate` | query | No | `string` | Inclusive end date. Defaults to today unless snapshotDate is provided. | | `snapshotDate` | query | No | `string` | Optional snapshot date. When provided, it is used as the effective end date. | | `headline` | query | No | `string` | Exact headline text to return as a single evolution series. Omit for global mode. | ## Responses ### 200 - Paginated headline evolution response. Pagination is by distinct headline series and the response includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `dateRange` | `object` | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`dateRange` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `startDate` | `string` | Yes | | | `endDate` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `headline` | `string` | Yes | | | `points` | `object`[] | Yes | | **`points[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `recordedAt` | `string` | Yes | Timestamp of the history snapshot used for this point. | | `activeAds` | `number` | Yes | | | `totalAds` | `number` | Yes | | | `euAds` | `number` | Yes | | | `euActiveAds` | `number` | Yes | | | `totalReach` | `number` | Yes | Total reach at this history point. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `percentNewAds` | `number` | Yes | | --- Tag: Brandtrackers · Reference: https://docs.trendtrack.io/docs/reference/api/brandtrackers#get-brandtracker-landing-page-evolution # Get brandtracker landing page evolution `GET /v1/brandtrackers/{brandtrackerId}/landing-page-evolution` Returns graph-ready landing page evolution series for one active workspace brandtracker resolved from brandtracker.id. Provide landingPage for exact single-page mode, or omit it to page through bounded global series ranked by active ads. **Tags:** Brandtrackers ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `brandtrackerId` | path | Yes | `string` | Public brandtracker identifier. This endpoint resolves brandtracker.id inside the authenticated workspace; legacy spyders.uuid values are accepted when migration metadata exists. | | `page` | query | No | `integer` | Pagination page number for global mode. Exact mode always returns at most one series. | | `limit` | query | No | `integer` | Number of series to return in global mode. Exact mode costs and returns one series. | | `startDate` | query | No | `string` | Inclusive start date. Defaults to 365 days before the effective end date. | | `endDate` | query | No | `string` | Inclusive end date. Defaults to today unless snapshotDate is provided. | | `snapshotDate` | query | No | `string` | Optional snapshot date. When provided, it is used as the effective end date. | | `landingPage` | query | No | `string` | Exact landing page URL to return as a single evolution series. Omit for global mode. | ## Responses ### 200 - Paginated landing page evolution response. Pagination is by distinct landing page series and the response includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `dateRange` | `object` | Yes | | | `pagination` | `object` | Yes | | | `meta` | `object` | Yes | | | `data` | `object`[] | Yes | | **`dateRange` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `startDate` | `string` | Yes | | | `endDate` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestedSnapshotDate` | `string` | Yes | Snapshot date requested by the client. Null when snapshotDate was omitted. | | `resolvedSnapshotDate` | `string` | Yes | Snapshot date actually used by the endpoint. Null when no ready snapshot was available or no snapshot resolution was needed. | | `dataFreshnessLagDays` | `number` | Yes | Difference in whole UTC days between today and the resolved snapshot date. Null when no snapshot was resolved. | | `periodNote` | `string` | No | Optional note clarifying period-specific freshness behavior. | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `landingPage` | `string` | Yes | | | `points` | `object`[] | Yes | | **`points[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | | | `recordedAt` | `string` | Yes | Timestamp of the history snapshot used for this point. | | `activeAds` | `number` | Yes | | | `totalAds` | `number` | Yes | | | `euAds` | `number` | Yes | | | `euActiveAds` | `number` | Yes | | | `totalReach` | `number` | Yes | Total reach at this history point. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric where available. | | `percentNewAds` | `number` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#list-boards # List boards `GET /v1/boards` **Tags:** Boards ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Filters: `scope`, `state`, `kind`, `surface`, `parentBoardId`, `rootOnly` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | No | `workspace` \| `personal` | | | `state` | query | No | `active` \| `archived` | | | `kind` | query | No | `folder` \| `collection` | | | `surface` | query | No | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Compatible destinations: Folders of this surface and mixed Folders. `mixed` lists only boards that accept every content type. | | `parentBoardId` | query | No | `string` | | | `rootOnly` | query | No | `boolean` | | | `page` | query | No | `number` | | | `limit` | query | No | `number` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#create-a-board # Create a board `POST /v1/boards` **Tags:** Boards ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | No | Every new board is a Folder. `collection` is deprecated and creates a mixed Folder. | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | No | The content type the Folder accepts. Omitted or null creates a mixed Folder, which accepts every content type. | | `description` | `string` | No | | | `visibility` | `private` \| `workspace` \| `public` | No | | | `parentBoardId` | `string` | No | | ## Responses ### 201 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#get-a-board # Get a board `GET /v1/boards/{boardId}` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#update-a-board # Update a board `PATCH /v1/boards/{boardId}` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | No | | | `description` | `string` | No | | | `visibility` | `private` \| `workspace` \| `public` | No | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#archive-a-board # Archive a board `DELETE /v1/boards/{boardId}` Archives the board subtree. The operation is reversible through the restore endpoint. **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#move-a-board # Move a board `PATCH /v1/boards/{boardId}/parent` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `parentBoardId` | `string` | Yes | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#restore-an-archived-board # Restore an archived board `POST /v1/boards/{boardId}/restore` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `name` | `string` | Yes | | | `kind` | `folder` \| `collection` | Yes | | | `surface` | `ads` \| `shops` \| `landing` \| `emails` \| `products` \| `advertisers` \| `mixed` | Yes | | | `description` | `string` | Yes | | | `createdByUserId` | `string` | Yes | | | `parentBoardId` | `string` | Yes | | | `workspaceId` | `string` | Yes | | | `visibility` | `private` \| `workspace` \| `public` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | | `archivedAt` | `string` | Yes | | | `capabilities` | `object` | Yes | | **`capabilities` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `canAddItems` | `boolean` | Yes | | | `canManage` | `boolean` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#list-board-item-references # List board item references `GET /v1/boards/{boardId}/items` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | | `page` | query | No | `number` | | | `limit` | query | No | `number` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `boardId` | `string` | Yes | | | `savedItemId` | `string` | Yes | | | `source` | `object` | Yes | | | `addedByUserId` | `string` | Yes | | | `position` | `number` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | **`source` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `sourceType` | `string` | Yes | | | `sourceId` | `string` | Yes | | | `sourceIndex` | `string` | No | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#add-an-item-to-a-board # Add an item to a board `POST /v1/boards/{boardId}/items` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `sourceType` | `meta_ad` \| `google_ad` \| `tiktok` \| `shop` \| `email` \| `product` \| `advertiser` | Yes | | | `sourceId` | `string` | Yes | | | `sourceIndex` | `string` | No | | | `position` | `number` | No | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `boardId` | `string` | Yes | | | `savedItemId` | `string` | Yes | | | `source` | `object` | Yes | | | `addedByUserId` | `string` | Yes | | | `position` | `number` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | **`source` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `sourceType` | `string` | Yes | | | `sourceId` | `string` | Yes | | | `sourceIndex` | `string` | No | | ### 201 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `boardId` | `string` | Yes | | | `savedItemId` | `string` | Yes | | | `source` | `object` | Yes | | | `addedByUserId` | `string` | Yes | | | `position` | `number` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | **`source` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `sourceType` | `string` | Yes | | | `sourceId` | `string` | Yes | | | `sourceIndex` | `string` | No | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#move-a-board-item # Move a board item `POST /v1/boards/{boardId}/items/{itemId}/move` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | | `itemId` | path | Yes | `string` | | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `targetBoardId` | `string` | Yes | | | `position` | `number` | No | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `boardId` | `string` | Yes | | | `savedItemId` | `string` | Yes | | | `source` | `object` | Yes | | | `addedByUserId` | `string` | Yes | | | `position` | `number` | Yes | | | `createdAt` | `string` | Yes | | | `updatedAt` | `string` | Yes | | **`source` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `sourceType` | `string` | Yes | | | `sourceId` | `string` | Yes | | | `sourceIndex` | `string` | No | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#remove-a-board-item # Remove a board item `DELETE /v1/boards/{boardId}/items/{itemId}` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | | `itemId` | path | Yes | `string` | | ## Responses ### 200 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `boardId` | `string` | Yes | | | `itemId` | `string` | Yes | | --- Tag: Boards · Reference: https://docs.trendtrack.io/docs/reference/api/boards#create-a-board-share-link # Create a board share link `POST /v1/boards/{boardId}/share-links` **Tags:** Boards ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `boardId` | path | Yes | `string` | | ## Responses ### 201 **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `boardId` | `string` | Yes | | | `url` | `string` | Yes | | | `createdAt` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#add-a-favorite-ad # Add a favorite ad `POST /v1/favorites/ads` Saves an ad to the requested workspace or delegated-user favorites scope. Existing favorites are returned idempotently without creating an audit mutation event. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scope` | `workspace` \| `personal` | Yes | | | `adId` | `string` | Yes | Composite public ad identifier, for example facebook_123 or tiktok_123. | | `folderId` | `object` | No | Favorite ads folder id (board id, or migrated V2 folder UUID). Null or omitted saves the ad in the scope's "Unsorted" board. | ## Responses ### 200 - Favorite ad mutation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | True when this call created a favorite; false when the favorite already existed. | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `ad` | `object` | Yes | Embedded public ad summary when the backing favorite can be resolved to a public-supported ad platform. | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#list-favorite-ads # List favorite ads `GET /v1/favorites/ads` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `folderId` | query | No | `string` | Optional ads folder identifier. This is the folder id (board id, or migrated V2 folder UUID). When provided, only favorites saved in that folder are returned. | ## Responses ### 200 - Paginated favorite ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `ad` | `object` | Yes | Embedded public ad summary when the backing favorite can be resolved to a public-supported ad platform. | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#move-a-saved-favorite-ad # Move a saved favorite ad `PATCH /v1/favorites/ads/saved/{favoriteId}/folder` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `favoriteId` | path | Yes | `string` | Saved favorite id, which is the board item id. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `folderId` | `object` | No | Favorite ads folder id (board id, or migrated V2 folder UUID). Null moves the saved ad to the scope's "Unsorted" board. | ## Responses ### 200 - Saved favorite ad move response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `ad` | `object` | Yes | Embedded public ad summary when the backing favorite can be resolved to a public-supported ad platform. | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#delete-a-saved-favorite-ad # Delete a saved favorite ad `DELETE /v1/favorites/ads/saved/{favoriteId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `favoriteId` | path | Yes | `string` | Saved favorite id, which is the board item id. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Responses ### 200 - Saved favorite ad removal response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `adId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folderId` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#remove-a-favorite-ad # Remove a favorite ad `DELETE /v1/favorites/ads/{adId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `adId` | path | Yes | `string` | Composite public ad identifier, for example facebook_123 or tiktok_123. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `folderId` | query | No | `string` | Favorite ads folder id (board id, or migrated V2 folder UUID). Omit to remove from the scope's "Unsorted" board. | ## Responses ### 200 - Favorite ad removal response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `adId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folderId` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#create-a-favorite-ad-folder # Create a favorite ad folder `POST /v1/favorites/ads/folders` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scope` | `workspace` \| `personal` | Yes | | | `name` | `string` | Yes | | | `parentId` | `object` | No | Parent folder id (board id, or migrated V2 folder UUID). Null or omitted creates a root folder. | ## Responses ### 200 - Favorite ad folder mutation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#list-favorite-ad-folders # List favorite ad folders `GET /v1/favorites/ads/folders` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `parentId` | query | No | `string` | Optional parent folder id (board id, or migrated V2 folder UUID). When provided, only direct children of that folder are returned. | | `rootOnly` | query | No | `boolean` | When true, returns only root folders. Cannot be combined with parentId. | ## Responses ### 200 - Paginated favorite ad folders response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#reorder-favorite-ad-folders # Reorder favorite ad folders `PATCH /v1/favorites/ads/folders/reorder` Boards have no manual order: the folders are validated and echoed back in the requested order, but no order is persisted. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `folders` | `object`[] | Yes | Folder UUID/order pairs to update in the requested scope. | **`folders[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Favorite ads folder id (board id, or migrated V2 folder UUID). | | `order` | `number` | Yes | | ## Responses ### 200 - Favorite ad folders reorder response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reordered` | `boolean` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folders` | `object`[] | Yes | | **`folders[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#create-a-favorite-ad-folder-share-url # Create a favorite ad folder share URL `POST /v1/favorites/ads/folders/{folderId}/share` Each call creates a new board share link. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Responses ### 200 - Public favorite ad folder share URL response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `folderId` | `string` | Yes | Board id of the shared folder. | | `folder` | `object` | Yes | | | `id` | `string` | Yes | Identifier of the board share link. | | `slug` | `string` | Yes | Always null: board share links have no slug. | | `shareUrl` | `string` | Yes | | | `sharePath` | `string` | Yes | | | `createdAt` | `string` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#set-favorite-ad-folder-visibility # Set favorite ad folder visibility `PATCH /v1/favorites/ads/folders/{folderId}/visibility` organization shares the board with the workspace; private is only allowed for folders created by the delegated user. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `visibility` | `private` \| `organization` | Yes | organization publishes a root folder tree to the API credential workspace. private converts a root folder tree to delegated-user personal scope when the delegated user owns all contained folders and saved ads. | ## Responses ### 200 - Favorite ad folder visibility response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#rename-or-move-a-favorite-ad-folder # Rename or move a favorite ad folder `PATCH /v1/favorites/ads/folders/{folderId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | No | | | `parentId` | `object` | No | Parent folder id (board id, or migrated V2 folder UUID). Use null to make it a root folder; omit to keep the current parent. | ## Responses ### 200 - Favorite ad folder mutation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id when the folder is nested. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#delete-a-favorite-ad-folder # Delete a favorite ad folder `DELETE /v1/favorites/ads/folders/{folderId}` The folder's board is archived, not destroyed: restore it with POST /v1/boards/{boardId}/restore. With move_items_to_root, items go to the scope's "Unsorted" board. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `mode` | `delete_items` \| `move_items_to_root` \| `move_items_to_folder` | Yes | Explicit handling for saved ads contained in the deleted folder tree. | | `targetFolderId` | `object` | No | Required when mode is move_items_to_folder. Must be a folder in the same requested scope and outside the deleted folder tree. | ## Responses ### 200 - Favorite ad folder delete response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `deleted` | `boolean` | Yes | | | `folderId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `mode` | `delete_items` \| `move_items_to_root` \| `move_items_to_folder` | Yes | | | `targetFolderId` | `string` | Yes | | | `deletedFolderIds` | `string`[] | Yes | | | `affectedFavoriteIds` | `string`[] | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#add-a-favorite-shop # Add a favorite shop `POST /v1/favorites/shops` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scope` | `workspace` \| `personal` | Yes | | | `websiteId` | `string` | Yes | Public website/shop identifier. The server resolves trusted domain and shop metadata from this id; clients cannot supply authoritative domain state. | | `folderId` | `object` | No | Favorite shops folder id (board id, or migrated V2 folder UUID). Null or omitted saves the shop in the scope's "Unsorted" board. | ## Responses ### 200 - Favorite shop mutation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | True when this call created a favorite; false when the favorite already existed. | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `shop` | `object` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** **`catalog` properties:** **`traffic` properties:** **`sales` properties:** **`advertising` properties:** **`tiktok` properties:** **`googleAds` properties:** **`latestAds[]` item properties:** --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#list-favorite-shops # List favorite shops `GET /v1/favorites/shops` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `folderId` | query | No | `string` | Optional shops folder identifier. When provided, only favorites saved in that folder are returned. | ## Responses ### 200 - Paginated favorite shops response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `shop` | `object` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** **`catalog` properties:** **`traffic` properties:** **`sales` properties:** **`advertising` properties:** **`tiktok` properties:** **`googleAds` properties:** **`latestAds[]` item properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#move-a-saved-favorite-shop # Move a saved favorite shop `PATCH /v1/favorites/shops/saved/{favoriteId}/folder` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `favoriteId` | path | Yes | `string` | Saved favorite id, which is the board item id. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `folderId` | `object` | No | Favorite shops folder id (board id, or migrated V2 folder UUID). Null moves the saved shop to the scope's "Unsorted" board. | ## Responses ### 200 - Saved favorite shop move response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `shop` | `object` | Yes | | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | **`shop` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `domain` | `string` | Yes | | | `name` | `string` | Yes | | | `screenshotUrl` | `string` | Yes | | | `createdAt` | `string` | Yes | | | `profile` | `object` | Yes | | | `catalog` | `object` | Yes | | | `traffic` | `object` | Yes | | | `sales` | `object` | No | Current sales estimate. Null when the sales tracker does not follow the shop. Present on shop-search rows; omitted by the deprecated favorites endpoints. | | `advertising` | `object` | Yes | | | `tiktok` | `object` | Yes | | | `googleAds` | `object` | No | Compact best-effort Google Ads summary hydrated for returned shop-search pages. When aggregation fails, status is unavailable and metric values are null. Present on shop-search rows; omitted by older summary producers that do not run Google Ads hydration. | | `latestAds` | `object`[] | Yes | Up to 3 most recent Meta ads published by the shop. | **`profile` properties:** **`catalog` properties:** **`traffic` properties:** **`sales` properties:** **`advertising` properties:** **`tiktok` properties:** **`googleAds` properties:** **`latestAds[]` item properties:** --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#delete-a-saved-favorite-shop # Delete a saved favorite shop `DELETE /v1/favorites/shops/saved/{favoriteId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `favoriteId` | path | Yes | `string` | Saved favorite id, which is the board item id. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Responses ### 200 - Saved favorite shop removal response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `websiteId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folderId` | `string` | Yes | | | `savedFavoriteId` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#remove-a-favorite-shop-by-website-id # Remove a favorite shop by website id `DELETE /v1/favorites/shops/{websiteId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `websiteId` | path | Yes | `string` | Public website/shop identifier. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `folderId` | query | No | `string` | Favorite shops folder id (board id, or migrated V2 folder UUID). Omit to remove from the scope's "Unsorted" board. | ## Responses ### 200 - Favorite shop removal response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `websiteId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folderId` | `string` | Yes | | | `savedFavoriteId` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#create-a-favorite-shop-folder # Create a favorite shop folder `POST /v1/favorites/shops/folders` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scope` | `workspace` \| `personal` | Yes | | | `name` | `string` | Yes | | ## Responses ### 200 - Favorite shop folder mutation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#list-favorite-shop-folders # List favorite shop folders `GET /v1/favorites/shops/folders` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | ## Responses ### 200 - Paginated favorite shop folders response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#set-favorite-shop-folder-visibility # Set favorite shop folder visibility `PATCH /v1/favorites/shops/folders/{folderId}/visibility` organization shares the board with the workspace; private is only allowed for folders created by the delegated user. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `visibility` | `private` \| `organization` | Yes | organization publishes a flat shop folder to the API credential workspace. private converts it to delegated-user personal scope when the delegated user owns the folder and every contained saved shop. | ## Responses ### 200 - Favorite shop folder visibility response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#rename-a-favorite-shop-folder # Rename a favorite shop folder `PATCH /v1/favorites/shops/folders/{folderId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | No | | ## Responses ### 200 - Favorite shop folder mutation response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#delete-a-favorite-shop-folder # Delete a favorite shop folder `DELETE /v1/favorites/shops/folders/{folderId}` The folder's board is archived, not destroyed: restore it with POST /v1/boards/{boardId}/restore. With move_items_to_root, items go to the scope's "Unsorted" board. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `mode` | `delete_items` \| `move_items_to_root` \| `move_items_to_folder` | Yes | Explicit handling for saved shops contained in the deleted flat folder. | | `targetFolderId` | `object` | No | Required when mode is move_items_to_folder. Must be a flat shops folder in the same requested scope. | ## Responses ### 200 - Favorite shop folder delete response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `deleted` | `boolean` | Yes | | | `folderId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `mode` | `delete_items` \| `move_items_to_root` \| `move_items_to_folder` | Yes | | | `targetFolderId` | `string` | Yes | | | `affectedFavoriteIds` | `string`[] | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#add-or-update-a-favorite-email # Add or update a favorite email `POST /v1/favorites/emails` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scope` | `workspace` \| `personal` | Yes | | | `emailId` | `number` | Yes | Public email identifier used by search/get_email_html. | | `folderId` | `object` | No | Favorite emails folder id (board id, or migrated V2 folder UUID). Null or omitted saves the email in the scope's "Unsorted" board. | ## Responses ### 200 - Favorite email mutation response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | | `created` | `boolean` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `email` | `object` | Yes | Embedded public email summary. Null when the saved row exists but the backing email content is no longer available. | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | **`email` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `sentAt` | `string` | Yes | | | `campaignType` | `string` | Yes | | | `classification` | `object` | Yes | | | `content` | `object` | Yes | | | `shop` | `object` | Yes | | **`classification` properties:** **`content` properties:** **`shop` properties:** --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#list-favorite-emails # List favorite emails `GET /v1/favorites/emails` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | | `folderId` | query | No | `string` | Optional emails folder id (board id, or migrated V2 folder UUID). When provided, only favorites saved in that folder are returned. | ## Responses ### 200 - Paginated favorite emails response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `email` | `object` | Yes | Embedded public email summary. Null when the saved row exists but the backing email content is no longer available. | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | **`email` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `sentAt` | `string` | Yes | | | `campaignType` | `string` | Yes | | | `classification` | `object` | Yes | | | `content` | `object` | Yes | | | `shop` | `object` | Yes | | **`classification` properties:** **`content` properties:** **`shop` properties:** **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#move-a-saved-favorite-email # Move a saved favorite email `PATCH /v1/favorites/emails/saved/{favoriteId}/folder` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `favoriteId` | path | Yes | `string` | Saved favorite id, which is the board item id. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `folderId` | `object` | No | Favorite emails folder id (board id, or migrated V2 folder UUID). Null moves the saved email to the scope's "Unsorted" board. | ## Responses ### 200 - Saved favorite email move response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Saved favorite id: the board item id. | | `scope` | `workspace` \| `personal` | Yes | | | `savedAt` | `string` | Yes | | | `folder` | `object` | Yes | | | `email` | `object` | Yes | Embedded public email summary. Null when the saved row exists but the backing email content is no longer available. | **`folder` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | **`email` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `number` | Yes | | | `sentAt` | `string` | Yes | | | `campaignType` | `string` | Yes | | | `classification` | `object` | Yes | | | `content` | `object` | Yes | | | `shop` | `object` | Yes | | **`classification` properties:** **`content` properties:** **`shop` properties:** --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#delete-a-saved-favorite-email # Delete a saved favorite email `DELETE /v1/favorites/emails/saved/{favoriteId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `favoriteId` | path | Yes | `string` | Saved favorite id, which is the board item id. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Responses ### 200 - Saved favorite email removal response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `emailId` | `number` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folderId` | `string` | Yes | | | `savedFavoriteId` | `string` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#create-a-favorite-email-folder # Create a favorite email folder `POST /v1/favorites/emails/folders` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `scope` | `workspace` \| `personal` | Yes | | | `name` | `string` | Yes | | | `parentId` | `object` | No | Parent folder id (board id, or migrated V2 folder UUID). Null or omitted creates a root folder. | ## Responses ### 200 - Favorite email folder mutation response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#list-favorite-email-folders # List favorite email folders `GET /v1/favorites/emails/folders` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | | ## Responses ### 200 - Paginated favorite email folders response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#reorder-favorite-email-folders # Reorder favorite email folders `PATCH /v1/favorites/emails/folders/reorder` Boards have no manual order: the folders are validated and echoed back in the requested order, but no order is persisted. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `folders` | `object`[] | Yes | | **`folders[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Favorite emails folder id (board id, or migrated V2 folder UUID). | | `order` | `number` | Yes | | ## Responses ### 200 - Favorite email folders reorder response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reordered` | `boolean` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folders` | `object`[] | Yes | | **`folders[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#set-favorite-email-folder-visibility # Set favorite email folder visibility `PATCH /v1/favorites/emails/folders/{folderId}/visibility` organization shares the board with the workspace; private is only allowed for folders created by the delegated user. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `visibility` | `private` \| `organization` | Yes | organization publishes a root email folder tree to the API credential workspace. private converts it to delegated-user personal scope when the delegated user owns every contained folder and saved email. | ## Responses ### 200 - Favorite email folder visibility response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#rename-or-move-a-favorite-email-folder # Rename or move a favorite email folder `PATCH /v1/favorites/emails/folders/{folderId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | `string` | No | | | `parentId` | `object` | No | Parent folder id (board id, or migrated V2 folder UUID). Use null to make it a root folder; omit to keep the current parent. | ## Responses ### 200 - Favorite email folder mutation response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Folder id: the id of the board backing the folder. | | `name` | `string` | Yes | | | `parentId` | `string` | Yes | Parent folder (board) id. Null for root folders. | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#delete-a-favorite-email-folder # Delete a favorite email folder `DELETE /v1/favorites/emails/folders/{folderId}` The folder's board is archived, not destroyed: restore it with POST /v1/boards/{boardId}/restore. With move_items_to_root, items go to the scope's "Unsorted" board. Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `folderId` | path | Yes | `string` | | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | ## Request Body **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `mode` | `delete_items` \| `move_items_to_root` \| `move_items_to_folder` | Yes | | | `targetFolderId` | `object` | No | | ## Responses ### 200 - Favorite email folder delete response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `deleted` | `boolean` | Yes | | | `folderId` | `string` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `mode` | `delete_items` \| `move_items_to_root` \| `move_items_to_folder` | Yes | | | `targetFolderId` | `string` | Yes | | | `deletedFolderIds` | `string`[] | Yes | | | `affectedFavoriteIds` | `string`[] | Yes | | --- Tag: Favorites · Reference: https://docs.trendtrack.io/docs/reference/api/favorites#remove-a-favorite-email-by-email-id # Remove a favorite email by email id `DELETE /v1/favorites/emails/{emailId}` Deprecated: favorites are now V3 boards; use /v1/boards. This endpoint is a compatibility facade over boards: folder ids are board ids (migrated V2 folder UUIDs are still accepted), saved favorite ids are board item ids, and favorites without a folder live in the scope's "Unsorted" board. **Tags:** Favorites ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `emailId` | path | Yes | `integer` | Public email identifier. To delete a saved favorite row by favorite_emails.uuid, use DELETE /v1/favorites/emails/saved/:favoriteId. | | `scope` | query | Yes | `workspace` \| `personal` | Favorites scope. Use personal only with a delegated_user credential. full_access credentials receive 403 for personal scope. | | `folderId` | query | No | `string` | Favorite emails folder id (board id, or migrated V2 folder UUID). Omit to remove from the scope's "Unsorted" board. | ## Responses ### 200 - Favorite email removal response. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object` | Yes | | **`data` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `removed` | `boolean` | Yes | | | `emailId` | `number` | Yes | | | `scope` | `workspace` \| `personal` | Yes | | | `folderId` | `string` | Yes | | | `savedFavoriteId` | `string` | Yes | | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#get-current-ranked-workspace-top-ads # Get current ranked workspace top ads `GET /v1/workspace/top-ads` Canonical current-ranking endpoint across active workspace brandtrackers in a single metered request. Each returned row is explicitly nested as { brandtracker, ad, metrics }. Billing remains proportional to requested/returned row count (limit/result length), not brandtracker count. Use sortBy=currentRank for current Facebook page rank, sortBy=reach/reachDelta1d/reachDelta7d/reachDelta30d for reach rankings, and sortBy=rankDelta7d/rankDelta14d/rankDelta30d for rank movers. period and snapshotDate are deprecated compatibility parameters and are ignored on this current-ranking path. **Tags:** Workspace ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | Pagination page number. Defaults to 1. | | `limit` | query | No | `integer` | Maximum number of workspace top ads to return. Must be <= 100. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `sortBy` | query | No | `currentRank` \| `rankDelta` \| `rankDelta7d` \| `rankDelta14d` \| `rankDelta30d` \| `reach` \| `reachDelta1d` \| `reachDelta7d` \| `reachDelta30d` \| `daysRunning` \| `duplicates` | Sort key for canonical current rankings. Use currentRank for current Facebook page rank (returned as rank/currentRank); rankDelta7d, rankDelta14d, or rankDelta30d for movers; reach, reachDelta1d, reachDelta7d, or reachDelta30d for reach rankings. | | `includeInactive` | query | No | `boolean` | When true, include inactive ads where supported. Defaults to false. | | `period` | query | No | `today` \| `yesterday` \| `last1d` \| `last7d` \| `last14d` \| `last30d` \| `total` | Optional rolling workspace top-ads period. Allowed values: today, yesterday, last1d, last7d, last14d, last30d, total. | | `snapshotDate` | query | No | `object` | Deprecated compatibility parameter accepted but ignored by canonical workspace top-ads current ranking. Use freshness/system endpoints for snapshot availability checks. | ## Responses ### 200 - Paginated workspace top ads response where each data row is { brandtracker, ad, metrics }. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | Request identifier mirrored in the X-Request-Id response header. | | `data` | `object`[] | Yes | Workspace top-ads rows. Every element uses the nested shape { brandtracker, ad, metrics }. | | `pagination` | `object` | Yes | | | `meta` | `object` | No | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtracker` | `object` | Yes | Brandtracker context for this workspace top-ads row. Each row is nested as { brandtracker, ad, metrics }. | | `ad` | `object` | Yes | Ad summary payload for this workspace top-ads row. Each row is nested as { brandtracker, ad, metrics }. | | `metrics` | `object` | Yes | Ranking/reach metrics for this workspace top-ads row. Each row is nested as { brandtracker, ad, metrics }. | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | Facebook page id associated with this workspace brandtracker. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `totalReach` | `number` | Yes | Total reach for the ranked ad. In Meta Ad Library vocabulary, reach is the public-facing impressions-style metric; EU impressions/reach are used where available. | | `duplicateCount` | `number` | Yes | | | `daysRunning` | `number` | Yes | | | `currentRank` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | **`meta` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `reason` | `no_snapshot_for_period` \| `no_reach_history_for_period` \| `no_matching_ads` | No | Present on empty result sets to distinguish filters with no matching ads. | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#get-workspace-hooks # Get workspace hooks `GET /v1/workspace/hooks` Returns hook analytics aggregated across active workspace brandtrackers in one metered request. One credit is charged per returned row. **Tags:** Workspace ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | Maximum number of workspace aggregate rows to return. Must be <= 100. | | `brandtrackerIds` | query | No | `string`[] | Optional comma-separated or repeated public brandtracker ids. | | `folderIds` | query | No | `integer`[] | Optional comma-separated or repeated workspace brandtracker folder ids. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | | | `sortBy` | query | No | `usageCount` \| `longestRunning` \| `totalImpressions` \| `firstUsedAt` \| `lastUsedAt` | | ## Responses ### 200 - Paginated workspace hooks response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtracker` | `object` | Yes | | | `hook` | `object` | Yes | | | `metrics` | `object` | Yes | | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | Facebook page id associated with this workspace brandtracker. | **`hook` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `text` | `string` | Yes | | | `sampleAd` | `object` | Yes | | **`sampleAd` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | | `totalImpressions` | `number` | Yes | | | `firstUsedAt` | `string` | Yes | | | `lastUsedAt` | `string` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#get-workspace-ad-copies # Get workspace ad copies `GET /v1/workspace/ad-copies` Returns ad copy analytics aggregated across active workspace brandtrackers in one metered request. One credit is charged per returned row. **Tags:** Workspace ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | Maximum number of workspace aggregate rows to return. Must be <= 100. | | `brandtrackerIds` | query | No | `string`[] | Optional comma-separated or repeated public brandtracker ids. | | `folderIds` | query | No | `integer`[] | Optional comma-separated or repeated workspace brandtracker folder ids. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | | | `sortBy` | query | No | `usageCount` \| `longestRunning` | | ## Responses ### 200 - Paginated workspace ad copies response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtracker` | `object` | Yes | | | `adCopy` | `object` | Yes | | | `metrics` | `object` | Yes | | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | Facebook page id associated with this workspace brandtracker. | **`adCopy` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `text` | `string` | Yes | | **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#get-workspace-landing-pages # Get workspace landing pages `GET /v1/workspace/landing-pages` Returns landing page analytics aggregated across active workspace brandtrackers in one metered request. One credit is charged per returned row. **Tags:** Workspace ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | Maximum number of workspace aggregate rows to return. Must be <= 100. | | `brandtrackerIds` | query | No | `string`[] | Optional comma-separated or repeated public brandtracker ids. | | `folderIds` | query | No | `integer`[] | Optional comma-separated or repeated workspace brandtracker folder ids. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `order` | query | No | `asc` \| `desc` | | | `sortBy` | query | No | `usageCount` \| `longestRunning` \| `totalImpressions` | | ## Responses ### 200 - Paginated workspace landing pages response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtracker` | `object` | Yes | | | `landingPage` | `object` | Yes | | | `metrics` | `object` | Yes | | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | Facebook page id associated with this workspace brandtracker. | **`landingPage` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `url` | `string` | Yes | | | `technologies` | `object`[] | Yes | | | `screenshots` | `object` | Yes | | **`technologies[]` item properties:** **`screenshots` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `usageCount` | `number` | Yes | | | `longestRunning` | `number` | Yes | | | `totalImpressions` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#get-workspace-scaling-ads-compatibility-data # Get workspace scaling ads compatibility data `GET /v1/workspace/scaling-ads` Legacy compatibility endpoint for clients that still call /workspace/scaling-ads. Prefer /v1/workspace/top-ads?sortBy=rankDelta7d, rankDelta14d, or rankDelta30d for canonical rank movers and sortBy=currentRank for current ranking. Endpoint key, billing, and response envelope remain stable; period and snapshotDate are deprecated and ignored on the ES-backed path, and trajectory may be empty. One credit is charged per returned row. **Tags:** Workspace ## Parameters **Query parameter groups:** - Pagination: `page`, `limit` - Time and snapshots: `period`, `snapshotDate` - Sorting: `sortBy` - Filters: `brandtrackerIds`, `folderIds`, `euOnly`, `maxCurrentRank`, `minRankDelta` | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | Maximum number of workspace aggregate rows to return. Must be <= 100. | | `brandtrackerIds` | query | No | `string`[] | Optional comma-separated or repeated public brandtracker ids. | | `folderIds` | query | No | `integer`[] | Optional comma-separated or repeated workspace brandtracker folder ids. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `period` | query | No | `today` \| `yesterday` \| `last1d` \| `last7d` \| `last14d` \| `last30d` \| `total` | Optional rolling period for workspace scaling ads. Allowed values: today, yesterday, last1d, last7d, last14d, last30d, total. | | `snapshotDate` | query | No | `object` | Deprecated compatibility parameter accepted but ignored on the ES-backed workspace scaling compatibility path. Use freshness/system endpoints for snapshot availability checks. | | `sortBy` | query | No | `rankDelta` \| `currentRank` \| `rank_delta` \| `current_rank` | | | `maxCurrentRank` | query | No | `integer` | | | `minRankDelta` | query | No | `integer` | | ## Responses ### 200 - Paginated workspace scaling ads response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtracker` | `object` | Yes | | | `ad` | `object` | Yes | | | `metrics` | `object` | Yes | | | `trajectory` | `object`[] | Yes | | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | Facebook page id associated with this workspace brandtracker. | **`ad` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | | | `collationId` | `string` | No | Creative collation identifier when this result represents a deduplicated group of related Meta ads. Pass this value as scan_ad.collation_id to scan the same combined creative shown by search. | | `platform` | `facebook` | Yes | | | `status` | `active` \| `inactive` \| `unknown` | Yes | For a result with collationId, active means at least one media-backed member ad is active. Without collationId, this is the individual ad status. | | `createdAt` | `string` | Yes | | | `firstSeenAt` | `string` | Yes | For a result with collationId, the earliest first-seen date across the combined creative members. | | `lastSeenAt` | `string` | Yes | For a result with collationId, null while any media-backed member remains active; otherwise the latest member end date. | | `daysRunning` | `number` | Yes | Indexed running duration in days. For a result with collationId, this is the creative calendar span from the oldest member start to today while any member is active, or to the latest member end otherwise; it does not imply continuous delivery by one ad. Historical backfill is bounded by the available firstSeenAt floor (currently 2018-01-01), so very old ads can share the same maximum/clamped value. | | `media` | `object` | Yes | | | `advertiser` | `object` | Yes | | | `content` | `object` | Yes | | | `metrics` | `object` | Yes | | | `audience` | `object` | Yes | | | `rank` | `object` | Yes | | | `flags` | `object` | Yes | | **`media` properties:** **`advertiser` properties:** **`content` properties:** **`metrics` properties:** **`audience` properties:** **`rank` properties:** **`flags` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `currentRank` | `number` | Yes | | | `previousRank` | `number` | Yes | | | `rankDelta` | `number` | Yes | Positive rank improvement over the selected comparison window. | | `improvementPct` | `object` | Yes | Percentage improvement from previousRank to currentRank over the selected comparison window. | **`trajectory[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `date` | `string` | Yes | Trajectory point date in YYYY-MM-DD format. | | `rank` | `number` | Yes | | | `totalAds` | `object` | Yes | Estimated total ranked ads for this snapshot when available. | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Workspace · Reference: https://docs.trendtrack.io/docs/reference/api/workspace#get-workspace-media-mix # Get workspace media mix `GET /v1/workspace/media-mix` Returns media mix rows across active workspace brandtrackers in one metered request. One credit is charged per returned row. **Tags:** Workspace ## Parameters | Name | In | Required | Type | Description | |------|-----|----------|------|-------------| | `page` | query | No | `integer` | | | `limit` | query | No | `integer` | Maximum number of workspace aggregate rows to return. Must be <= 100. | | `brandtrackerIds` | query | No | `string`[] | Optional comma-separated or repeated public brandtracker ids. | | `folderIds` | query | No | `integer`[] | Optional comma-separated or repeated workspace brandtracker folder ids. | | `euOnly` | query | No | `boolean` | Optional EU-only filter. When true, only EU-classified Facebook ads are included. | | `sortBy` | query | No | `activeAds` \| `image` \| `video` \| `dco` \| `other` | | ## Responses ### 200 - Paginated workspace media mix response. The response also includes the X-Request-Id header. **Content-Type:** `application/json` **Properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `requestId` | `string` | Yes | | | `data` | `object`[] | Yes | | | `pagination` | `object` | Yes | | **`data[]` item properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `brandtracker` | `object` | Yes | | | `mediaMix` | `object` | Yes | | | `metrics` | `object` | Yes | | **`brandtracker` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `id` | `string` | Yes | Public brandtracker identifier backed by brandtracker.id. Legacy spyders.uuid values are accepted when migration metadata exists. | | `name` | `string` | Yes | | | `facebookPageId` | `string` | Yes | Facebook page id associated with this workspace brandtracker. | **`mediaMix` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `formatCount` | `object` | Yes | Workspace media mix exposes image, video, dco, and other only. Carousel is not available as a separate bucket. | **`formatCount` properties:** **`metrics` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `activeAds` | `number` | Yes | | **`pagination` properties:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `page` | `number` | Yes | | | `limit` | `number` | Yes | | | `total` | `number` | Yes | | | `totalPages` | `number` | Yes | | --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpController_handleMcpRequest `POST /v1/mcp` ## Responses ### 200 --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpController_handleMcpHeadRequest `HEAD /v1/mcp` ## Responses ### 200 --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpController_handleMcpGetRequest `GET /v1/mcp` ## Responses --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpController_handleMcpDeleteRequest `DELETE /v1/mcp` ## Responses --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpMetadataController_getProtectedResourceMetadata `GET /.well-known/oauth-protected-resource/v1/mcp` ## Responses ### 200 --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpMetadataController_getProtectedResourceMetadataRoot `GET /.well-known/oauth-protected-resource` ## Responses ### 200 --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpAuthServerMetadataController_getAuthorizationServerMetadata `GET /.well-known/oauth-authorization-server/v1/mcp` ## Responses ### 200 --- Tag: Other · Reference: https://docs.trendtrack.io/docs/reference/api-reference # PublicApiMcpAuthServerMetadataController_getAuthorizationServerMetadataRoot `GET /.well-known/oauth-authorization-server` ## Responses ### 200