curl --request GET \
--url https://brew.new/api/v1/domains/{domainId}/health \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/domains/{domainId}/health"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://brew.new/api/v1/domains/{domainId}/health', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://brew.new/api/v1/domains/{domainId}/health",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://brew.new/api/v1/domains/{domainId}/health"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://brew.new/api/v1/domains/{domainId}/health")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/domains/{domainId}/health")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"domainId": "kx7bkh53hasmfeh5kd7sqgykt187g8ww",
"name": "send.example.com",
"status": "verified",
"sendable": true,
"verdict": "at_risk",
"authentication": {
"spf": "verified",
"dkim": "verified",
"dmarc": "missing"
},
"tracking": {
"linksStatus": "live",
"openTracking": true,
"clickTracking": true
},
"warmup": [
{
"sendId": "snd_x1",
"currentTranche": 3,
"sentSoFar": 175,
"rampEndsAt": "2026-07-15T00:00:00.000Z"
}
],
"dailyVolume": [
{
"day": "2026-07-11T00:00:00.000Z",
"sent": 50
},
{
"day": "2026-07-12T00:00:00.000Z",
"sent": 63
}
],
"domainActivity": {
"sampled": true,
"sampleSendCount": 12,
"sentCount": 2400,
"bouncedCount": 31,
"complainedCount": 1,
"bounceRate": 0.0129,
"complaintRate": 0.0004
},
"orgReputation": {
"scope": "org",
"totalSent": 18250,
"bounceRate": 0.011,
"complaintRate": 0.0003
},
"recentPlacementTests": [
{
"testId": "ibp_2f1c9d8a",
"emailId": "eml_welcome",
"status": "completed",
"overall": {
"total": 41,
"inbox": 33,
"spam": 8,
"missing": 0,
"pending": 0
},
"authentication": {
"spf": "pass",
"dkim": "pass",
"dmarc": "pass"
},
"spamFilterFlagged": false,
"createdAt": "2026-07-13T17:00:00.000Z"
}
],
"signals": [
{
"id": "dmarc_missing",
"severity": "warning",
"summary": "No DMARC record is configured for this domain.",
"suggestion": "Add a TXT record: _dmarc TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@send.example.com\" — Gmail/Yahoo bulk-sender rules require DMARC, and it blocks spoofing."
}
],
"checkedAt": "2026-07-13T18:00:00.000Z"
}{
"error": {
"code": "INVALID_API_KEY",
"type": "authentication_error",
"message": "The provided API key is invalid.",
"suggestion": "Check the API key format and retry with a valid active key.",
"docs": "https://docs.brew.new/api-reference/api/authentication"
}
}{
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"type": "authorization_error",
"message": "The caller does not have the required permission.",
"suggestion": "Use an API key or session with the required permission.",
"docs": "https://docs.brew.new/api-reference/api/authentication",
"param": "domains"
}
}{
"error": {
"code": "DOMAIN_NOT_FOUND",
"type": "not_found",
"message": "The requested domain 'dom_xxx' was not found.",
"suggestion": "List domains with GET /v1/domains.",
"docs": "https://docs.brew.new/api-reference/api/errors",
"param": "domainId"
}
}{
"error": {
"code": "RATE_LIMITED",
"type": "rate_limit",
"message": "Too many requests.",
"suggestion": "Wait for the retry window before sending another request.",
"docs": "https://docs.brew.new/api-reference/api/rate-limits",
"retryAfter": 42
}
}{
"error": {
"code": "INTERNAL_ERROR",
"type": "internal_error",
"message": "An unexpected error occurred.",
"suggestion": "Retry the request. If it keeps failing, contact support.",
"docs": "https://docs.brew.new/api-reference/api/errors"
}
}Get domain health
The domain’s deliverability health in one FREE read: a verdict (healthy / at_risk / critical) with actionable signals, DNS/auth state incl. DMARC, active percentage-based gradual sends + recent UTC-day volume, general bounce/complaint reporting, workspace reputation, and inbox-placement history. No bounce or complaint threshold is attached to a gradual-send configuration.
curl --request GET \
--url https://brew.new/api/v1/domains/{domainId}/health \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/domains/{domainId}/health"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://brew.new/api/v1/domains/{domainId}/health', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://brew.new/api/v1/domains/{domainId}/health",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://brew.new/api/v1/domains/{domainId}/health"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://brew.new/api/v1/domains/{domainId}/health")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/domains/{domainId}/health")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"domainId": "kx7bkh53hasmfeh5kd7sqgykt187g8ww",
"name": "send.example.com",
"status": "verified",
"sendable": true,
"verdict": "at_risk",
"authentication": {
"spf": "verified",
"dkim": "verified",
"dmarc": "missing"
},
"tracking": {
"linksStatus": "live",
"openTracking": true,
"clickTracking": true
},
"warmup": [
{
"sendId": "snd_x1",
"currentTranche": 3,
"sentSoFar": 175,
"rampEndsAt": "2026-07-15T00:00:00.000Z"
}
],
"dailyVolume": [
{
"day": "2026-07-11T00:00:00.000Z",
"sent": 50
},
{
"day": "2026-07-12T00:00:00.000Z",
"sent": 63
}
],
"domainActivity": {
"sampled": true,
"sampleSendCount": 12,
"sentCount": 2400,
"bouncedCount": 31,
"complainedCount": 1,
"bounceRate": 0.0129,
"complaintRate": 0.0004
},
"orgReputation": {
"scope": "org",
"totalSent": 18250,
"bounceRate": 0.011,
"complaintRate": 0.0003
},
"recentPlacementTests": [
{
"testId": "ibp_2f1c9d8a",
"emailId": "eml_welcome",
"status": "completed",
"overall": {
"total": 41,
"inbox": 33,
"spam": 8,
"missing": 0,
"pending": 0
},
"authentication": {
"spf": "pass",
"dkim": "pass",
"dmarc": "pass"
},
"spamFilterFlagged": false,
"createdAt": "2026-07-13T17:00:00.000Z"
}
],
"signals": [
{
"id": "dmarc_missing",
"severity": "warning",
"summary": "No DMARC record is configured for this domain.",
"suggestion": "Add a TXT record: _dmarc TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@send.example.com\" — Gmail/Yahoo bulk-sender rules require DMARC, and it blocks spoofing."
}
],
"checkedAt": "2026-07-13T18:00:00.000Z"
}{
"error": {
"code": "INVALID_API_KEY",
"type": "authentication_error",
"message": "The provided API key is invalid.",
"suggestion": "Check the API key format and retry with a valid active key.",
"docs": "https://docs.brew.new/api-reference/api/authentication"
}
}{
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"type": "authorization_error",
"message": "The caller does not have the required permission.",
"suggestion": "Use an API key or session with the required permission.",
"docs": "https://docs.brew.new/api-reference/api/authentication",
"param": "domains"
}
}{
"error": {
"code": "DOMAIN_NOT_FOUND",
"type": "not_found",
"message": "The requested domain 'dom_xxx' was not found.",
"suggestion": "List domains with GET /v1/domains.",
"docs": "https://docs.brew.new/api-reference/api/errors",
"param": "domainId"
}
}{
"error": {
"code": "RATE_LIMITED",
"type": "rate_limit",
"message": "Too many requests.",
"suggestion": "Wait for the retry window before sending another request.",
"docs": "https://docs.brew.new/api-reference/api/rate-limits",
"retryAfter": 42
}
}{
"error": {
"code": "INTERNAL_ERROR",
"type": "internal_error",
"message": "An unexpected error occurred.",
"suggestion": "Retry the request. If it keeps failing, contact support.",
"docs": "https://docs.brew.new/api-reference/api/errors"
}
}Authorizations
Send your Brew API key as Authorization: Bearer brew_xxx.
Headers
The brand this request acts on. REQUIRED for organization-scoped credentials (otherwise 400 BRAND_ID_REQUIRED — there is no default brand); list ids with GET /v1/brands. Brand-scoped credentials may omit it, and sending a different brand returns 403 BRAND_SCOPE_MISMATCH. A brand outside your organization returns 404 BRAND_NOT_FOUND.
1 - 64Path Parameters
Domain id (opaque Convex document id) returned by POST /v1/domains and listed by GET /v1/domains.
1 - 64"kx7bkh53hasmfeh5kd7sqgykt187g8ww"
Response
The aggregate health report.
1 - 641 - 253not_started, pending, verified, failed, temporary_failure, partially_verified, partially_failed healthy, at_risk, critical ready, ready_with_warnings, not_ready, checking, unknown Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Was this page helpful?