Check whether a sending domain's infrastructure is blocklisted
/v1/email/inbox-insights/blocklists// Requires Insights preview access for the organization.
let sendingDomain: string | undefined;
for await (const domain of bird.email.inboxInsights.domains.list({ search: "mail.example.com" })) {
if (domain.domain === "mail.example.com") { sendingDomain = domain.domain; break; }
}
if (!sendingDomain) throw new Error("Verify mail.example.com in this workspace first");
const report = await bird.email.inboxInsights.blocklists({ sending_domain: sendingDomain });
console.log(report);# Requires Insights preview access for the organization.
sending_domain = None
for domain in client.email.inbox_insights.domains.list(search="mail.example.com"):
if domain.domain == "mail.example.com":
sending_domain = domain.domain
break
if sending_domain is None:
raise ValueError("Verify mail.example.com in this workspace first")
report = client.email.inbox_insights.blocklists(sending_domain=sending_domain)
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()
sendingDomain := ""
for domain, err := range client.Email.InboxInsights.Domains.List(ctx, bird.EmailInboxInsightsDomainsListParams{Search: "mail.example.com"}) {
if err != nil {
log.Fatal(err)
}
if domain.Domain != nil && *domain.Domain == "mail.example.com" {
sendingDomain = *domain.Domain
break
}
}
if sendingDomain == "" {
log.Fatal("Verify mail.example.com in this workspace first")
}
report, err := client.Email.InboxInsights.Blocklists(ctx, bird.EmailInboxInsightsBlocklistsParams{SendingDomain: sendingDomain})
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.
$sendingDomain = null;
foreach ($bird->email->inboxInsights->domains->list(['search' => 'mail.example.com']) as $domain) {
if ($domain->getDomain() === 'mail.example.com') {
$sendingDomain = $domain->getDomain();
break;
}
}
if ($sendingDomain === null) {
throw new \RuntimeException('Verify mail.example.com in this workspace first');
}
$report = $bird->email->inboxInsights->blocklists(['sending_domain' => $sendingDomain]);
var_dump($report);bird email inbox-insights blocklists <sending-domain>curl -X GET "https://us1.platform.bird.com/v1/email/inbox-insights/blocklists" \
-H "Authorization: Bearer $TOKEN" \
--url-query "sending_domain=mail.acme.com"{
"resource": "placement",
"domain": "mail.acme.com",
"measurement": {
"sources": [
"panel",
"intelliseed_public"
],
"weighting": {
"weight_set_id": "12",
"source": "account",
"basis": "weighted-mean-of-per-isp-rates"
}
},
"generated_at": "2026-08-18T09:34:00Z",
"freshness": {
"as_of": "2026-08-17",
"lag_hint": "daily"
},
"cached_at": "2026-08-18T09:40:02Z",
"active_count": 0,
"targets": [
{
"target": "147.253.40.18",
"target_type": "ip",
"is_listed": false,
"status": "ok",
"checked_at": "2026-08-20T09:12:04Z",
"listings": [
{
"is_active": false,
"reason_code": "CSS",
"provider": "Spamhaus CSS",
"reason": "Automated listing of a suspected snowshoe range",
"first_detected": "2026-07-31T00:00:00Z",
"last_detected": "2026-08-04T00:00:00Z"
}
]
}
]
}
Checks the sending IPs behind a sending domain against the blocklists receivers consult, and returns what is listed now plus the listings seen recently against each target. The vendor's default target selection includes IPs seen sending in the last 30 days and the domain itself. The returned targets and their statuses describe the coverage of this lookup; an empty target list does not establish that the domain or its IPs are clear. The 30-day period selects targets; listing status reflects the current lookup.
The check runs when the request is made, so this is a live lookup rather than a measurement over a period: there is no window, and only the freshness lag hint applies. Providers that publish several lists are reported per list, because what a listing means and how it is cleared differ between them.
Each target is looked up separately, so one can fail while the rest
succeed. A target nobody managed to check comes back with its status
reporting that and its checked_at null, rather than as a target that
came back clear. active_count is null when the lookup service supplies no
count; do not treat null as zero. Zero does not establish complete coverage:
inspect the returned targets and their statuses. A 503 means Bird
could not reach the lookup service at all, which is a different answer from
a lookup that ran and reported nothing.
API-key calls require Insights preview access for your organization.
Query Parameters
sending_domainstringThe sending domain to check: one of the workspace's verified sending domains, exactly as it appears there. Inspect the returned targets and their statuses for lookup coverage. A domain that is not verified in this workspace answers not-found.
Response Payload
resourceWhich resource this response is, echoed for self-description.
domainThe sending domain the figures describe.
measurementHow the figures were measured. Present only where a figure was weighted or drawn from a named set of sources, which today means placement and the industry benchmark. Absent on the reputation resources and on a live lookup, neither of which weights anything.
generated_atWhen these figures were computed. The measurement service's own stamp where it publishes one; on the resources Bird derives from daily rates it has none to publish, and this is when Bird computed them.
freshnessHow current the figures are. Freshness differs per resource (authentication data can lag a day or more while blocklist lookups are near real time), so any "as of" label binds from this field, never from a fixed string.
cached_atPresent when the response was served from a short-lived copy rather than fetched for this request: when that copy was fetched.
active_countNumber of successfully checked targets reported with an active listing. A target on three blocklists counts once. Null when the lookup service supplies no count; do not treat null as zero. Zero does not establish that the domain or its IPs were checked. Inspect targets and each target's status for lookup coverage, including partial failures.
targetsReturned sending IP or domain lookup results, including failed lookups. An empty array does not establish that the domain or its IPs are clear.
Show child attributes
targets.targetThe sending IP or domain selected for lookup.
targets.target_typeWhether this target is an IP address or a hostname. Null when the measurement did not report a kind for it, which is possible on a target whose check did not complete.
Possible values (may grow over time): ip, domain
targets.is_listedWhether the target is on at least one blocklist right now. Meaningful only when status is ok: on any other status this target was not checked, so the value carries no finding either way.
targets.statusWhether this target was actually checked. unavailable means the lookup failed or timed out for this target while others may have succeeded, so the honest rendering is "could not check" rather than a result.
Possible values: ok, no_data, not_configured, unavailable, not_applicable
targets.checked_atWhen this target was looked up, or null when it was not. Per target rather than per response, because each is a separate live lookup.
targets.listingsListings seen against this target, including ones that have since cleared, so a recent history is visible even when nothing is active. Read each listing's is_active rather than assuming every entry is current.
Show child attributes
targets.listings.is_activeWhether this listing is in force now. A false entry is history: it shows the target was listed and has since cleared, which is why the target's is_listed can be false while listings are present.
targets.listings.reason_codeThe provider's own short code for the listing reason, or null when it gives none. Stable where the prose in reason is not, so branch on this and display that.
targets.listings.providerThe blocklist that carries the listing. Providers publishing several lists are reported per list rather than under one combined name, because what a listing means and how it is cleared differ per list.
targets.listings.reasonThe reason the provider gives for the listing, or null when it publishes none.
targets.listings.first_detectedWhen this listing was first observed.
targets.listings.last_detectedWhen this listing was most recently observed, or null while the listing is still in force. A provider records a last sighting only once one exists, so a null here reads as "still listed" rather than "never seen".
Related resources
Continue with the documentation, guides and examples for this topic.