Get when a watched brand sends
/v1/email/competitive/watchlist/brands/{watchlist_brand_id}/send-time// Requires Insights preview access for the organization.
const watchlist = await bird.email.competitive.watchlist.get({ range: 30 });
const entry = watchlist.data.find((row) => row.name === "Everlane" && row.watchlist_brand_id);
if (!entry?.watchlist_brand_id) throw new Error("Add Everlane to the watchlist first");
const watchlistBrandId = entry.watchlist_brand_id;
const report = await bird.email.competitive.watchlist.brands.sendTime(watchlistBrandId, { timezone: "UTC" });
console.log(report);# Requires Insights preview access for the organization.
watchlist = client.email.competitive.watchlist.get(range=30)
entry = next((row for row in watchlist.data if row.name == "Everlane" and row.watchlist_brand_id), None)
if entry is None or entry.watchlist_brand_id is None:
raise ValueError("Add Everlane to the watchlist first")
watchlist_brand_id = entry.watchlist_brand_id
report = client.email.competitive.watchlist.brands.send_time(watchlist_brand_id, timezone="UTC")
print(report.model_dump_json())// Requires Insights preview access for the organization.
client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
watchlist, err := client.Email.Competitive.Watchlist.Get(ctx, bird.EmailCompetitiveWatchlistGetParams{Range: 30})
if err != nil {
log.Fatal(err)
}
watchlistBrandID := ""
if watchlist.Data != nil {
for _, row := range *watchlist.Data {
if row.Name != nil && *row.Name == "Everlane" && row.WatchlistBrandId != nil {
watchlistBrandID = string(*row.WatchlistBrandId)
break
}
}
}
if watchlistBrandID == "" {
log.Fatal("Add Everlane to the watchlist first")
}
report, err := client.Email.Competitive.Watchlist.Brands.SendTime(ctx, watchlistBrandID, bird.EmailCompetitiveWatchlistBrandsSendTimeParams{Timezone: "UTC"})
if err != nil {
log.Fatal(err)
}
encoded, err := json.MarshalIndent(report, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(encoded))// Requires Insights preview access for the organization.
$watchlist = $bird->email->competitive->watchlist->get(['range' => 30]);
$watchlistBrandId = null;
foreach ($watchlist->getData() ?? [] as $row) {
if ($row->getName() === 'Everlane' && $row->getWatchlistBrandId() !== null) {
$watchlistBrandId = $row->getWatchlistBrandId();
break;
}
}
if ($watchlistBrandId === null) {
throw new \RuntimeException('Add Everlane to the watchlist first');
}
$report = $bird->email->competitive->watchlist->brands->sendTime($watchlistBrandId, ['timezone' => 'UTC']);
var_dump($report);bird email competitive watchlist brands send-time <watchlist-brand-id>curl -X GET "https://us1.platform.bird.com/v1/email/competitive/watchlist/brands/{watchlist_brand_id}/send-time" \
-H "Authorization: Bearer $TOKEN"{
"period": {
"days": 30,
"from": "2026-07-13T09:00:00Z",
"to": "2026-08-12T09:00:00Z"
},
"timezone": "America/New_York",
"panel_status": "ok",
"cells": [
{
"weekday": "tuesday",
"hour": 13,
"share_percent": 3.4,
"intensity": 0.55,
"sample_days": 13
}
],
"peak_send_window": {
"start_hour": 13,
"end_hour": 14,
"share_percent": 13.1
}
}
Returns how a watched brand's sending is spread across the week: one figure per weekday and hour of the day, over the last 90 days, with the hour of the day it sends most of its mail in.
Each hour counts when the brand sent, not when its subscribers opened or received the mail. It answers "when does this brand mail its list", which is what a competing send has to be timed against. It says nothing about how busy a subscriber's inbox was at that hour.
Hours are reported in the timezone you ask for, echoed back in timezone, and the
week is folded into that zone before it is totalled, so a send at 02:00 UTC on
Monday counts as Sunday evening in New York. Label an axis from timezone rather than from what you asked for: a
response the panel could not answer reports UTC regardless.
Expect the weekday axis to look flat. For most brands the hour of the day is where the pattern is, and which day of the week it is barely moves the figure; a grid with little variation down its rows is a real finding about how the brand mails rather than a gap in the data.
API-key calls require Insights preview access for your organization.
Parameters
watchlist_brand_idstringThe watchlist entry whose sending pattern to return.
Query Parameters
timezonestringIANA timezone identifier to report send times in; defaults to UTC. The grid is folded into this zone before it is summed, so a send lands on the weekday and hour it happened at locally rather than the one it happened at in UTC. A zone this API does not know returns 422 rather than falling back to UTC, so an axis is never labelled with a zone the figures were not folded into.
Response Payload
periodThe period the grid covers. It is always the last 90 days, whatever range the rest of the brand's figures are shown over: an hour of the week comes round about thirteen times in 90 days and once in a week, and a pattern drawn from one observation per cell is noise.
Two things differ from the other competitive reads. It ends at the start of a day rather than at the moment of the request, and the panel answers repeat requests from a cache it holds for a day, so two requests a minute apart return identical figures and this grid can be up to a day behind the figures shown beside it.
Show child attributes
period.daysLength of the period in days.
period.fromStart of the period, inclusive.
period.toEnd of the period, exclusive. Daily figures therefore run through the previous whole UTC day and never include the one in progress.
timezoneThe timezone the hours are reported in. Label the grid from this rather than from what was requested: a response the panel could not answer reports UTC whatever was asked for.
panel_statusWhy the grid is empty, when it is.
Possible values: ok, not_in_panel, no_data, unavailable
cellsEvery weekday and hour of the week, Monday first and hour ascending: 168 in all, whether or not the brand sent in them, so the grid needs no filling in. Empty when there was nothing to read, which panel_status explains.
peak_send_windowThe hour of the day the brand sends most of its mail in, totalled across the whole week, or null when nothing was observed. It carries no weekday: for most brands the hour of the day is where the pattern is and the day of the week barely moves, so naming a busiest weekday would give a figure more meaning than it has. It is also not always the darkest cell, on the same reasoning: one busy Wednesday can outweigh the hour the brand mails in every single day.
Related resources
Continue with the documentation, guides and examples for this topic.