curl --request GET \
--url https://brew.new/api/v1/insights \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/insights"
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', 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",
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"
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")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/insights")
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{
"data": [
{
"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"
}
],
"pagination": {
"limit": 100,
"cursor": null,
"hasMore": false
},
"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"
}
},
"pulse": {
"windowEnd": "2026-10-02T00:00:00.000Z",
"delivered": 12400,
"priorDelivered": 11900,
"uniqueOpens": 4960,
"priorUniqueOpens": 4400,
"uniqueClicks": 620,
"priorUniqueClicks": 590,
"unsubscribed": 18,
"priorUnsubscribed": 21,
"openRatePct": 40,
"priorOpenRatePct": 37,
"clickRatePct": 5,
"priorClickRatePct": 5,
"openDirection": "up",
"clickDirection": "steady",
"countsOnly": false,
"measured": true
}
}List insights
The brand’s Brew Insights as the Insights page ranks them, most severe first and then by score, under { data, pagination, freshness }. Each row is one deterministic finding of the insight engine; the engine keeps at most 200 findings in view.
Use when reporting what Brew found about the brand’s email: deliverability problems, campaigns that under- or over-performed, timing, audience and automation opportunities.
Input state (open, the default: active findings and snoozes that have ended; or all, which adds resolved, cleared, dismissed and stale findings), severity to read one severity (up to 200 of its own, however many more severe findings exist), limit/cursor to page. A cursor belongs to the walk that returned it: it continues only the same state and severity, and only while the findings it already returned are still the rows before it. A finding added, removed or moved further down is served when its page comes, so a walk returns each finding of the list as it stands at its last page exactly once. include adds the intelligence layer the page shows beside the findings: pulse (the last 7 days against the 7 before), report (the latest report the analysis agent published), suggestions (its proposed and launched suggestions, up to 25) and memo (the agent’s memory across runs).
Returns 200. Each row carries insightId, title, description (the detector’s headline), severity, confidence, kind, category, detectorId, state, firstSeenAt, lastSeenAt, recurrenceCount, an optional action and the finding’s url in Brew. freshness is on every page: dataAsOf is how current the data behind the findings is, and latestAttempt.status: failed means they may be stale. An expansion that does not exist yet answers null. Read-only and free.
Errors 400 INVALID_REQUEST for an unknown query key, value or include token, or a malformed cursor. Also 400 INVALID_REQUEST with param: cursor when the findings changed since the cursor was issued (one it already returned left the list or moved, or a new finding ranks among them; the engine re-ran, or a finding was snoozed, dismissed or changed state): read again from the first page, without cursor. A cursor issued for another state or severity is refused the same way.
See also getInsight, getAnalyticsOverview.
curl --request GET \
--url https://brew.new/api/v1/insights \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/insights"
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', 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",
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"
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")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/insights")
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{
"data": [
{
"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"
}
],
"pagination": {
"limit": 100,
"cursor": null,
"hasMore": false
},
"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"
}
},
"pulse": {
"windowEnd": "2026-10-02T00:00:00.000Z",
"delivered": 12400,
"priorDelivered": 11900,
"uniqueOpens": 4960,
"priorUniqueOpens": 4400,
"uniqueClicks": 620,
"priorUniqueClicks": 590,
"unsubscribed": 18,
"priorUnsubscribed": 21,
"openRatePct": 40,
"priorOpenRatePct": 37,
"clickRatePct": 5,
"priorClickRatePct": 5,
"openDirection": "up",
"clickDirection": "steady",
"countsOnly": false,
"measured": true
}
}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 - 64Query Parameters
open (default) lists active findings and snoozes that have ended. all adds resolved, cleared, dismissed and stale findings and snoozes still in effect.
open, all Only findings of this severity: critical, warning, opportunity or info, up to 200 of its own.
critical, warning, opportunity, info Comma-separated expansions: pulse adds the weekly pulse, report the latest intelligence report, suggestions its open suggestions (up to 25), memo the analysis agent’s memo.
Page size (1-100). Defaults to 100.
1 <= x <= 10050
1 - 512Response
A page of findings, the engine’s freshness and any expansions asked for.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
With include pulse: the weekly pulse, or null before the first run.
Show child attributes
Show child attributes
With include report: the latest intelligence report, or null when none was published.
Show child attributes
Show child attributes
With include suggestions: proposed and launched suggestions, most recently updated first.
25Show child attributes
Show child attributes
With include memo: the memo, or null before the first run.
Show child attributes
Show child attributes
Was this page helpful?