Emails
The email endpoints let you explore the emails brands send their subscribers: marketing newsletters, abandoned-cart reminders, and sign-up confirmations. Search every email we track, pull one brand's emails, sample a trending feed, and chart how brands send. On this page, we will look at the email record and every email endpoint.
Every email comes with a screenshot_url, a picture of the whole email as the subscriber saw it. Screenshot URLs expire 3 days after the response is issued, like every other image URL in the API. Re-fetch the email when you need a fresh one, or use the download endpoint to get the image itself.
The email endpoints work the way the ad endpoints do: the same { data, pagination } response, the same pagination, the same fields= selection, and the same brand-side filters.
The email record
Default fields
id, brand_id, timestamp, type, subject, preview_text, from_name, from_email, email_provider, screenshot_url, plus dashboard_url on every row.
All available fields
- Name
id- Type
- string
- Description
The email's identifier. Every email endpoint takes it, and it is always returned.
- Name
brand_id- Type
- string
- Description
The brand that sent the email (its domain, e.g.
retro-stage.com). Always returned.
- Name
timestamp- Type
- string
- Description
When the email was sent (ISO 8601, UTC).
- Name
type- Type
- string
- Description
What kind of email it is:
marketing(newsletters and campaigns),abandoned_cart(reminders about a cart left behind), orsubscription_confirmation(the welcome after a sign-up). SeeGET /v1/facets/email-types.
- Name
subject- Type
- string
- Description
The subject line, as plain text.
- Name
preview_text- Type
- string
- Description
The preview line shown next to the subject in the inbox, as plain text. Absent when the email has none.
- Name
from_name- Type
- string
- Description
The sender name shown in the inbox.
- Name
from_email- Type
- string
- Description
The sender address.
- Name
reply_to- Type
- string
- Description
The reply-to address, when the email sets one.
- Name
email_provider- Type
- string
- Description
The email platform the brand sent it with (
shopify,klaviyo,omnisend,mailchimp, …), when we can tell.
- Name
has_checkout- Type
- boolean
- Description
truefor an abandoned-cart email. An older flag thattypereplaces: filter ontype=abandoned_cartinstead.
- Name
has_unsubscribe- Type
- boolean
- Description
Whether the email carries an unsubscribe link.
- Name
link_count- Type
- integer
- Description
How many links the email contains.
- Name
image_count- Type
- integer
- Description
How many images the email contains.
- Name
screenshot_url- Type
- string
- Description
A picture of the whole email. Expires 3 days after the response is issued.
- Name
dashboard_url- Type
- string
- Description
The email's page in the Brandsearch app.
reply_to, has_checkout, has_unsubscribe, link_count, and image_count are returned only when you ask for them with fields=. id, brand_id, screenshot_url, and dashboard_url come back whatever you select. GET /v1/facets/fields lists the fields under emails.
Sort fields
timestamp (the send date, the default), link_count, image_count. Aliases: recent, date, and sent for timestamp; links for link_count; images for image_count.
Emails sent in the last hour may not be listed yet, because their screenshot is still being prepared. They appear in every list once it is ready, and fetching one by its id works straight away.
Email filters
Every endpoint that lists emails accepts these filters.
- Name
q- Type
- string
- Description
Search the subject line and the preview text. The words must appear in order, and the last one may be the start of a word, so
black frimatches "Black Friday". Separate alternatives with two spaces to match any of them (up to 5):black friday cyber monday. Max 200 characters. A small share of emails store punctuation in an encoded form that a phrase containing an apostrophe or an ampersand does not match; searching on the words around it finds them.
- Name
type- Type
- string
- Description
One or more email types, comma-separated:
marketing,abandoned_cart,subscription_confirmation. Case-insensitive. Any other value is a400 invalid_parameter.
- Name
sent_from- Type
- string
- Description
Emails sent on or after this date.
YYYY-MM-DDmeans the start of that day in UTC; an ISO 8601 timestamp or unix seconds is an exact moment.
- Name
sent_to- Type
- string
- Description
Emails sent on or before this date.
YYYY-MM-DDincludes that whole day in UTC, sosent_from=2026-09-01&sent_to=2026-09-01returns the emails sent on September 1.
- Name
sort_by- Type
- string
- Description
timestamp(default),link_count, orimage_count, or one of their aliases.
- Name
sort_order- Type
- string
- Description
desc(default) orasc. Unlike the ad endpoints,sort_order=ascon its own lists the oldest emails first.
- Name
fields- Type
- string
- Description
Comma-separated list of email fields to return.
Search emails
Search every email we track across all brands, newest first. Combine the email filters with any brand-side filter to narrow it to the brands you care about.
Costs 1 credit per email returned.
Search and email filters
q, type, sent_from, sent_to, sort_by, sort_order, fields: see email filters.
Brand-side filters
All brand-side filters work here: niche, monthly_visits_min/max, markets, country_code, currency_code, apps, techs, payments, platform, min_revenue_*, max_revenue_*, meta_ads_active, product_count_min/max, and their _exclude forms.
Results come from at most 10,000 of the brands a brand-side filter matches, and pagination.total counts only their emails. A broad filter such as niche=Fashion matches far more brands than that, so narrow it (by country or traffic, for example) when you need complete results. brand_ids is not limited this way.
- Name
brand_ids- Type
- string
- Description
Comma-separated brand IDs (max 200). Only emails from these brands are returned.
Pagination & output
- Name
page- Type
- integer
- Description
Page number. Default
1. A search can be paged through its first 10,000 results; a page past that is a400 invalid_parameterwhosedetails.max_pagenames the last page you can reach.
- Name
page_size- Type
- integer
- Description
Results per page (1-100). Default
20.
- Name
max_emails_per_brand- Type
- integer
- Description
Cap how many emails from any single brand appear on a page (1-20).
pagination.totalstill counts every matching email, and a page can come back a little shorter thanpage_sizewhen a few brands send most of the top results.
Request
curl -G https://api.brandsearch.co/v1/emails/search \
-H "X-API-Key: bsk_your_api_key" \
-d q="black friday" \
-d niche=Fashion \
-d sent_from=2026-01-01 \
-d page_size=2
Response
{
"data": [
{
"id": "3510c738f80186f20e6dfae84a4c8543",
"brand_id": "freecountry.com",
"timestamp": "2026-07-26T19:01:03.635000+00:00",
"type": "marketing",
"subject": "60% Off Select Styles + Free Shipping Today Only!",
"preview_text": "FINAL HOURS: 55% OFF all summer styles during our Black Friday in July Sale!",
"from_name": "Free Country",
"from_email": "noreply@freecountry.com",
"screenshot_url": "https://cdn.brandsearch.co/emails/3510c738f80186f20e6dfae84a4c8543.png",
"dashboard_url": "https://app.brandsearch.co/emails/3510c738f80186f20e6dfae84a4c8543"
}
],
"pagination": {
"page": 1,
"page_size": 2,
"total": 10,
"total_pages": 5
}
}
Query emails (JSON body)
The same search as GET /v1/emails/search, with the filters in a JSON body. Use it when the filter set is too long for a URL. List filters (type, brand_ids, niche, apps, markets, …) take real arrays, and page / page_size go inside the body. An unknown key is a 400 validation_error.
Costs 1 credit per email returned.
cURL
curl https://api.brandsearch.co/v1/emails/query \
-H "X-API-Key: bsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"type": ["abandoned_cart"],
"brand_ids": ["retro-stage.com", "ryzesuperfoods.com"],
"sent_from": "2026-06-01",
"page": 1,
"page_size": 20
}'
List a brand's emails
One brand's emails, newest first: the Emails tab of the brand's page in the Brandsearch app. An unknown brand returns an empty page rather than an error.
Accepts the email filters (q, type, sent_from, sent_to, sort_by, sort_order, fields), plus page (default 1) and page_size (1-100, default 20).
Costs 1 credit per email returned.
Request
curl -G https://api.brandsearch.co/v1/brands/retro-stage.com/emails \
-H "X-API-Key: bsk_your_api_key" \
-d type=abandoned_cart \
-d page_size=2
Response
{
"data": [
{
"id": "bfd7c60dd0d6156e78f6b186beb96095",
"brand_id": "retro-stage.com",
"timestamp": "2026-09-15T23:44:52.186000+00:00",
"type": "abandoned_cart",
"subject": "Hurry! Your cart is about to expire!",
"preview_text": "This is your last chance",
"from_name": "Retro Stage - Chic Vintage Dresses and Accessories",
"from_email": "service@retro-stage.com",
"screenshot_url": "https://cdn.brandsearch.co/emails/bfd7c60dd0d6156e78f6b186beb96095.png",
"dashboard_url": "https://app.brandsearch.co/emails/bfd7c60dd0d6156e78f6b186beb96095"
}
],
"pagination": {
"page": 1,
"page_size": 2,
"total": 8,
"total_pages": 4
}
}
Discover emails
A random sample of marketing emails from trending brands: brands in top markets and currencies with real traffic, or recently added. Build an inspiration feed around it. The sample changes on every call unless you pin seed.
Costs 1 credit per email returned.
- Name
limit- Type
- integer
- Description
Sample size (1-500). Default
30.
- Name
seed- Type
- string
- Description
Reproducibility seed (max 64 characters). The same seed and filters return the same sample. The response echoes the seed it used.
- Name
max_emails_per_brand- Type
- integer
- Description
Cap how many emails from any single brand appear in the sample (1-20).
- Name
type- Type
- string
- Description
Replaces the default,
marketing, with the types you list.
- Name
sent_from- Type
- string
- Description
The sample spans every send date unless you set this. Pass a recent date for recent emails only.
q, sent_to, and fields work as in the email filters, and the brand-side filters narrow the brands the sample is drawn from. brand_ids and country_code are not supported here and are ignored: use search to pull specific brands.
cURL
curl -G https://api.brandsearch.co/v1/emails/discover \
-H "X-API-Key: bsk_your_api_key" \
-d limit=2 \
-d seed=newsletter-ideas
Response
{
"data": [
{
"id": "87fc2d07e5dc120b437aaa2d354ebfe3",
"brand_id": "maydetea.com",
"timestamp": "2026-05-20T23:33:02.404000+00:00",
"type": "marketing",
"subject": "Almost Brewed!",
"preview_text": "Don't let this be the one that got away ☕️",
"from_name": "Mayde Tea",
"from_email": "hello@maydetea.com",
"screenshot_url": "https://cdn.brandsearch.co/emails/87fc2d07e5dc120b437aaa2d354ebfe3.png",
"dashboard_url": "https://app.brandsearch.co/emails/87fc2d07e5dc120b437aaa2d354ebfe3"
}
],
"seed": "newsletter-ideas",
"count": 2
}
Get an email
One email, by the id a list response gave you. Takes fields=. An unknown id is a 404 ad_not_found, and is not charged.
Costs 1 credit.
cURL
curl -G https://api.brandsearch.co/v1/emails/90f2c592da1c8d06770513ed7702abdf \
-H "X-API-Key: bsk_your_api_key" \
-d fields=subject,link_count,image_count,has_checkout,has_unsubscribe
Response
{
"id": "90f2c592da1c8d06770513ed7702abdf",
"brand_id": "retro-stage.com",
"subject": "Halloween Is Coming! Secure Your Spooky Style. 🕸️",
"link_count": 49,
"image_count": 31,
"has_checkout": false,
"has_unsubscribe": true,
"screenshot_url": "https://cdn.brandsearch.co/emails/90f2c592da1c8d06770513ed7702abdf.png",
"dashboard_url": "https://app.brandsearch.co/emails/90f2c592da1c8d06770513ed7702abdf"
}
Download an email screenshot
Returns the screenshot's image bytes rather than a link. screenshot_url expires, and some clients cannot fetch images from another host at all; this route serves the same picture over your API connection.
Costs 1 credit, charged only when the image is served. An email whose screenshot is missing returns 404 ad_media_unavailable and is not charged.
- Name
size- Type
- string
- Description
full(default) for the original PNG, orcompactfor a JPEG at most 800 px wide and 8,000 px tall, much lighter for a long email.
- Name
media- Type
- string
- Description
auto(default) orimage, both the screenshot. An email has no video, somedia=videois a400 ad_media_not_video.
Response headers: Content-Disposition, X-Ad-Media-Kind: image, X-Ad-Media-Size (full or compact), and X-Ad-Platform: email.
cURL
curl -G https://api.brandsearch.co/v1/emails/bfd7c60dd0d6156e78f6b186beb96095/download \
-H "X-API-Key: bsk_your_api_key" \
-d size=compact \
-o email.jpg
AI analysis of an email
An AI creative breakdown of the email, read from its screenshot: concept, angle, hook, target audience, funnel stage, copy strategy, suggested tests, and more. It is the same analysis the email view of the Brandsearch app produces, and the two share results, so an email analysed in the app comes back instantly here and the other way round.
Costs 14 AI credits, and no request credit. A previously generated analysis comes back free. Pass {"force_regenerate": true} to run it again, which charges again. 402 insufficient_ai_credits when your balance cannot cover it; nothing is generated or charged. When the email's screenshot cannot be read, the analysis is refused with 503 service_unavailable and nothing is charged; try again later.
GET on the same path returns a previously generated analysis for free, or 404 ai_analysis_not_found when there is none yet.
The response has the same shape as the AI analysis of an ad.
cURL
curl -X POST https://api.brandsearch.co/v1/emails/90f2c592da1c8d06770513ed7702abdf/ai-analysis \
-H "X-API-Key: bsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{}'
Response
{
"analysis": {
"concept": "Halloween Vintage Style Sale",
"angle": "Seasonal urgency and diverse vintage-inspired spooky fashion at discounted prices.",
"hook": "Halloween Is Coming! Secure Your Spooky Style.",
"funnelStage": "MOF",
"cta": "SHOP NOW",
"...": "..."
},
"model": "BrandSearch",
"generated_at": "2026-09-24T19:56:14.026429+00:00",
"cached": false,
"cost": 14,
"ai_credits": { "used": 433, "total": 2000, "remaining": 1567 }
}
Email aggregates
Breakdowns over any slice of emails: how many, which types, which brands send the most, and on which days. The body takes the same filters as POST /v1/emails/query, without pagination.
Costs a flat 1 credit, however many emails the slice holds.
- Name
window- Type
- object
- Description
email_count, and thefirst_sentandlast_sentdates of the slice.
- Name
type_mix- Type
- object
- Description
Emails per type:
marketing,abandoned_cart,subscription_confirmation, andotherfor the rare email without one.
- Name
brand_mix- Type
- object
- Description
The 50 brands with the most emails in the slice, with their counts.
- Name
send_day- Type
- object
- Description
Emails per calendar day (UTC). Days without an email are left out.
- Name
send_weekday- Type
- object
- Description
The same counts summed per weekday (UTC),
mondaytosunday.
cURL
curl https://api.brandsearch.co/v1/emails/aggregates \
-H "X-API-Key: bsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{"brand_ids": ["retro-stage.com"]}'
Response
{
"window": {
"email_count": 634,
"first_sent": "2026-03-20T14:12:41.316Z",
"last_sent": "2026-09-24T17:52:11.135Z"
},
"type_mix": {
"marketing": 626,
"abandoned_cart": 8,
"subscription_confirmation": 0,
"other": 0
},
"brand_mix": { "retro-stage.com": 634 },
"send_day": { "2026-03-20": 6, "2026-03-21": 5, "...": "..." },
"send_weekday": {
"monday": 81,
"tuesday": 79,
"wednesday": 94,
"thursday": 87,
"friday": 96,
"saturday": 105,
"sunday": 92
}
}
Errors
The email endpoints return the same errors as the ad endpoints:
400 invalid_parameteror400 validation_errorfor a bad value, withdetails.parameternaming it. Nothing is charged.404 ad_not_foundfor an unknown emailid.404 ad_media_unavailablewhen an email's screenshot is missing (download only).402 insufficient_ai_creditsand404 ai_analysis_not_foundon the AI analysis.
See Errors for the full list.