curl --request GET \
--url https://brew.new/api/v1/insights/{insightId} \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/insights/{insightId}"
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/insights/{insightId}', 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/insights/{insightId}",
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/insights/{insightId}"
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/insights/{insightId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/insights/{insightId}")
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{
"insightId": "k17a8m2v4w5x6y7z8a9b0c1d2e3f4g5h",
"title": "Spring sale",
"description": "Spring sale bounced 6.2% of sends, above the 6% line.",
"severity": "critical",
"confidence": "high",
"kind": "insight",
"category": "deliverability",
"detectorId": "deliv.bounce_rate_breach",
"state": "active",
"firstSeenAt": "2026-10-01T12:00:00.000Z",
"lastSeenAt": "2026-10-02T06:04:12.000Z",
"recurrenceCount": 1,
"action": {
"kind": "navigate",
"label": "Open campaign analytics",
"url": "https://brew.new/analytics/sends/Vx2mZ8t9QbY3sW1vR0pLd"
},
"url": "https://brew.new/insights/k17a8m2v4w5x6y7z8a9b0c1d2e3f4g5h",
"rationale": "Mailbox providers start filtering a sender whose campaigns bounce above 6%.",
"closedReason": null,
"closedAt": null,
"lastActedAt": null,
"churnCount": 0,
"metrics": {
"bounceRate": {
"kind": "rate",
"value": 0.062,
"numerator": 62,
"denominator": 1000,
"basis": "sent"
},
"bounced": {
"kind": "count",
"value": 62,
"noun": "bounces"
}
},
"evidence": [
{
"label": "62 bounced, 3 unsubscribed"
}
],
"subject": {
"kind": "campaign",
"id": "Vx2mZ8t9QbY3sW1vR0pLd",
"label": "Spring sale"
},
"method": {
"what": "A campaign whose bounce rate crosses the level mailbox providers act on.",
"how": "Bounced ÷ sent, compared against fixed thresholds: 3% is a warning, 6% is critical.",
"comparedAgainst": "Absolute industry thresholds, not your own history: providers do not grade on a curve.",
"resolvesWhen": "A later send of the same campaign stays under 3%, usually after cleaning the list."
},
"generatedBy": {
"trigger": "send_settled",
"startedAt": "2026-10-02T06:00:03.000Z",
"completedAt": "2026-10-02T06:04:12.000Z",
"blindSpots": []
},
"freshness": {
"dataAsOf": "2026-10-02T06:00:00.000Z",
"lastSuccessfulRunAt": "2026-10-02T06:04:12.000Z",
"latestAttempt": {
"status": "succeeded",
"at": "2026-10-02T06:04:12.000Z"
}
}
}Get an insight
One finding in full, as its page in Brew reads it: the list row’s fields plus rationale, closedReason, closedAt, lastActedAt, churnCount, the frozen metrics, evidence links, its subject, the detector’s method (what it measures, how, against what, and what resolves it), generatedBy (the engine run that produced it and what that run could not see) and freshness.
Use when explaining why a finding exists or what would resolve it. metrics were frozen when the finding was computed and are the only numbers to quote about it.
Input insightId in the path, as a listInsights row carries it.
Returns 200 with the finding. Read-only and free.
Errors 404 INSIGHT_NOT_FOUND for an unknown, malformed or over-long id OR a finding of another brand: one identical error, so the cases are indistinguishable.
See also listInsights.
curl --request GET \
--url https://brew.new/api/v1/insights/{insightId} \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/insights/{insightId}"
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/insights/{insightId}', 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/insights/{insightId}",
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/insights/{insightId}"
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/insights/{insightId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/insights/{insightId}")
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{
"insightId": "k17a8m2v4w5x6y7z8a9b0c1d2e3f4g5h",
"title": "Spring sale",
"description": "Spring sale bounced 6.2% of sends, above the 6% line.",
"severity": "critical",
"confidence": "high",
"kind": "insight",
"category": "deliverability",
"detectorId": "deliv.bounce_rate_breach",
"state": "active",
"firstSeenAt": "2026-10-01T12:00:00.000Z",
"lastSeenAt": "2026-10-02T06:04:12.000Z",
"recurrenceCount": 1,
"action": {
"kind": "navigate",
"label": "Open campaign analytics",
"url": "https://brew.new/analytics/sends/Vx2mZ8t9QbY3sW1vR0pLd"
},
"url": "https://brew.new/insights/k17a8m2v4w5x6y7z8a9b0c1d2e3f4g5h",
"rationale": "Mailbox providers start filtering a sender whose campaigns bounce above 6%.",
"closedReason": null,
"closedAt": null,
"lastActedAt": null,
"churnCount": 0,
"metrics": {
"bounceRate": {
"kind": "rate",
"value": 0.062,
"numerator": 62,
"denominator": 1000,
"basis": "sent"
},
"bounced": {
"kind": "count",
"value": 62,
"noun": "bounces"
}
},
"evidence": [
{
"label": "62 bounced, 3 unsubscribed"
}
],
"subject": {
"kind": "campaign",
"id": "Vx2mZ8t9QbY3sW1vR0pLd",
"label": "Spring sale"
},
"method": {
"what": "A campaign whose bounce rate crosses the level mailbox providers act on.",
"how": "Bounced ÷ sent, compared against fixed thresholds: 3% is a warning, 6% is critical.",
"comparedAgainst": "Absolute industry thresholds, not your own history: providers do not grade on a curve.",
"resolvesWhen": "A later send of the same campaign stays under 3%, usually after cleaning the list."
},
"generatedBy": {
"trigger": "send_settled",
"startedAt": "2026-10-02T06:00:03.000Z",
"completedAt": "2026-10-02T06:04:12.000Z",
"blindSpots": []
},
"freshness": {
"dataAsOf": "2026-10-02T06:00:00.000Z",
"lastSuccessfulRunAt": "2026-10-02T06:04:12.000Z",
"latestAttempt": {
"status": "succeeded",
"at": "2026-10-02T06:04:12.000Z"
}
}
}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
The insightId a GET /v1/insights row carries.
"k17a8m2v4w5x6y7z8a9b0c1d2e3f4g5h"
Response
The finding.
What the finding is about.
The detector’s deterministic headline; quote it, never restate its numbers.
critical, warning, opportunity, info high, medium, low answer reports what happened, insight a change that passed its statistical test, strategy a recommended next step.
answer, insight, strategy A snooze that has ended reads as active.
active, snoozed, cleared, dismissed, resolved, stale x >= 0The finding’s page in Brew.
How often the finding has closed and reopened.
x >= 0Frozen when the finding was computed: the only numbers to quote about it.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
What the finding is about: a send, an automation, a domain.
Show child attributes
Show child attributes
How the detector works; null when none is recorded.
Show child attributes
Show child attributes
The engine run that last produced the finding.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
- Option 1
- Option 2
Show child attributes
Show child attributes
Was this page helpful?