Brand ids
{id} in a path accepts two forms:
- the platform id — the brand’s id on the platform it advertises from. It’s
numeric for brands (
1234567890) and a handle for creators (saschafitness). This is what/brands/searchreturns asid. - the brand UUID —
a1b2c3d4-.... Accepted if you already have one, but search never returns this form.
404 brand_not_found.
Nothing is paginated
There is no cursor, nopage, and no total. Each collection endpoint returns
up to its cap in one response, and count is the number of rows in that
response — not how many exist.
If count equals the limit you asked for, assume there is more data you
didn’t get, and raise the limit.
Two endpoints have no headroom to raise: /brands/{id}/landing-pages has a
default and a maximum that are both 100, and /brands/search with
mode: "smart" returns at most 20 however high you set count. For those, a
full page means you have all the API will give you, not that you asked for too
little.
Ordering
Because results are ranked, truncating with
limit keeps the strongest rows —
you lose the tail, not an arbitrary subset.
Modes take different fields
/brands/search validates a different shape per mode, and these rules can’t be
expressed in JSON Schema, so a generated client won’t catch them:
mode: "ids"requiresbrandIds.countis ignored — you get one row per id that matches a brand. Ids that match nothing don’t raise404; they come back inunmatchedIds, sobrandscan be shorter than the list you sent. You’re billed only for the rows you got.mode: "brand_name"requiresbrandNamesandtype.mode: "smart"requiresqueryandtype, and rejectssortBy, because results are ordered by relevance.
400 invalid_request with the offending field in details.
Rate limits
Three limits apply at once, and the lowest wins:- 60 requests/minute per IP address
- 120 requests/minute per key
- a per-endpoint limit:
- 60/min for
/brands/search,GET /brands/{id}, andPOST /brands/{id}/media - 50/min for
POST /brands/index - 300/min for
GET /brands/{id}/index-status - 30/min for
/insightsand/landing-pages
- 60/min for
429 rate_limited with a Retry-After header.
Wait that many seconds rather than retrying immediately.
Note the per-IP limit is lower than the per-key limit and is checked first, so a
single server making concurrent calls will hit 60/min before it hits 120/min.
For /brands/search, GET /brands/{id}, and POST /brands/{id}/media the
per-endpoint limit is also 60/min, so the per-IP limit reaches it first and the
per-endpoint one never fires on its own. GET /brands/{id}/index-status is
300/min, so IP and key limits win first there too. POST /brands/index (50/min)
and the 30/min endpoints can report a per-endpoint 429.
Requests and responses
- Server-to-server only. There’s no CORS, so browser calls will fail. Keep the key on your backend.
- POST bodies are capped at 100 KB. Larger returns
413 payload_too_large. - Responses are never cached — every response carries
Cache-Control: no-store. HEADis not supported on/insights,/landing-pages, and/index-status. It returns405 method_not_allowed. On the meteredGETendpoints that’s because it would run the query and bill for it without returning a body.- Any other wrong method — a
GETon aPOSTpath, say — also returns405 method_not_allowed, with anAllowheader listing what the path accepts.