Rate Limiting
The Brandsearch API enforces rate limits and quotas to ensure fair usage. This page explains how they work, how to read your own limits, and how to handle them.
Rate limits
Rate limits protect the API from bursts. The same limits apply to every API key — they do not depend on your plan — and they are checked over several time windows at once, from one second up to one day. A separate set of limits applies per IP address, which matters if you run many keys from one server. It also counts requests with a missing, invalid or revoked key: a burst of rejected requests from one address can get 429 rate_limited before the key is even checked.
You do not need to know the numbers in advance, because every response tells you where you stand:
X-RateLimit-Limitis the ceiling of whichever window you are closest to filling;X-RateLimit-Remainingis what is left in that window;X-RateLimit-Resetis when it empties.
When you go over, the API answers 429 rate_limited with a Retry-After header, and names the window you filled in details.window (1s, 1m, 1h or 1d). See Handling rate limits below.
Rate limit exceeded response
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded.",
"details": {
"retry_after": 12,
"window": "1m"
}
}
}
Quotas
In addition to rate limits, each API key has a request quota: a ceiling on how many requests you can make per day and per month.
Your quota comes from your API subscription, which you manage from the API tab of your dashboard. A regular Brandsearch subscription includes a small API allowance, an API plan raises it, and without a paid subscription the allowance is zero. There is no fixed table on this page — plans change and allowances can be customised — so the API tells you your own numbers instead:
- every response that returns data — searches, lists, single records — carries
X-Quota-Daily-LimitandX-Quota-Monthly-Limit(your ceilings) next toX-Quota-Daily-RemainingandX-Quota-Monthly-Remaining(what is left); GET /v1/usagereturns the same ceilings and counters at any time, and it is unmetered, so checking costs nothing.
On current plans the daily ceiling is set equal to the monthly one, so the monthly figure is the one that matters in practice.
When a quota is used up, requests answer 429 quota_exceeded, with details.quota_type (daily or monthly) and details.limit, until that counter resets.
Correction: this page used to list quotas and rate limits per plan. Those numbers were wrong. They did not match what any account is actually granted, and rate limits have never depended on the plan. If you sized a job from them, read your real ceilings from X-Quota-Monthly-Limit or GET /v1/usage instead — they can be much lower than what was printed here.
Quotas reset automatically — daily quotas reset at midnight UTC, and monthly quotas reset on the 1st of each month.
Free (unmetered) endpoints
Some endpoints don't count against your quota:
GET /v1/lookup— resolve a name/domain/handle to a brand IDGET /v1/me— your account infoGET /v1/usage— live quota countersGET /v1/facets/*— enumerate valid filter/sort/field valuesGET /v1/swipe/mobile-feed/*— read the mobile feed and its folders, so watching for new posts costs nothing
These responses include X-Quota-Charged: false so you can verify the request was not metered.
Credits (per-row tracking)
In addition to request count, every metered response carries an X-Credits-Used header showing how many credits the request cost. Credits are charged per returned row, and a brand costs twice as much as an ad:
- Brand rows cost 2 credits each. A
page_size=20brand list costs up to 40 credits. This applies wherever brand records are returned:GET /v1/brands,GET /v1/brands/discover,POST /v1/brands/query,POST /v1/brands/by-ids, and the two swipe-file endpoints that resolve a folder to brands. - Ad and post rows cost 1 credit each, so a
page_size=20ad list costs up to 20 credits. - Detail endpoints charge for the one record they return: 2 credits for a brand (
GET /v1/brands/{brand_id},GET /v1/brands/by-url/{url}), 1 credit for an ad or post (GET /v1/meta-ads/{ad_id}, etc.). - Emails cost 1 credit each, like ads: per email returned by a search, a discover sample, or a brand's email list, and 1 credit to fetch or download one email. Email aggregates cost a flat 1 credit.
- Products cost 1 credit each: per product returned by a search, a market, a batch of URLs or a brand's catalogue, and 1 credit to open one product or download its image. An unknown product costs none.
- Ad transcription (
POST /v1/meta-ads/{ad_id}/transcription) charges 1 credit per transcript returned, and nothing if the call fails. - Free endpoints above charge 0 credits.
Correction: a brand costs 2 credits, not 1. This has been the rate since API version 1.6.0 (7 May 2026), but this page and the endpoint pages said 1 credit per row until now. Nothing has changed in what you are charged — the X-Credits-Used header has reported the right number all along. If you sized a budget from the old figure, double the part of it that fetches brands.
Credits are currently informational — there is no daily or monthly limit on credits yet, but counters (credits_used_today, credits_used_this_month) are exposed via GET /v1/usage.
Response headers
Every API response includes headers showing your current quota usage:
- Name
X-Quota-Daily-Remaining- Type
- integer
- Description
Requests remaining for the current day.
- Name
X-Quota-Monthly-Remaining- Type
- integer
- Description
Requests remaining for the current month.
- Name
X-Quota-Daily-Limit- Type
- integer
- Description
Your total daily limit.
- Name
X-Quota-Monthly-Limit- Type
- integer
- Description
Your total monthly limit.
- Name
X-Quota-Overrun- Type
- string
- Description
Present with value
"true"when the response exceeded quota.
- Name
X-Quota-Overrun-Daily- Type
- integer
- Description
Number of daily overage requests (only when overrun).
- Name
X-Quota-Overrun-Monthly- Type
- integer
- Description
Number of monthly overage requests (only when overrun).
- Name
X-RateLimit-Limit- Type
- integer
- Description
Maximum requests allowed in the most-constrained rate-limit window.
- Name
X-RateLimit-Remaining- Type
- integer
- Description
Requests remaining in that window after the current one.
- Name
X-RateLimit-Reset- Type
- integer
- Description
Unix timestamp (seconds) when the most-constrained window expires and the counter resets.
- Name
Retry-After- Type
- integer
- Description
Seconds to wait before retrying (on
429responses).
- Name
X-Credits-Used- Type
- integer
- Description
Credits charged for this request: 2 per brand returned, 1 per ad or post returned, 0 on free endpoints.
- Name
X-Quota-Charged- Type
- string
- Description
Set to
"false"on unmetered endpoints (/v1/lookup,/v1/me,/v1/usage,/v1/facets/*).
Handling rate limits
When you hit a rate limit, the API returns a 429 status with a Retry-After header. The best practice is to implement exponential backoff:
Handling rate limits
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options)
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '1')
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000))
continue
}
return response
}
throw new Error('Max retries exceeded')
}
Monitor your X-Quota-Daily-Remaining and X-Quota-Monthly-Remaining headers to proactively manage your usage and avoid hitting limits.