curl --request GET \
--url https://brew.new/api/v1/flows/{slug} \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/flows/{slug}"
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/flows/{slug}', 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/flows/{slug}",
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/flows/{slug}"
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/flows/{slug}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/flows/{slug}")
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{
"slug": "brew.new",
"brand": {
"name": "Brew",
"logo": "https://cdn.brew.new/brand/fetched-logo/brew.new/logo.png"
},
"title": "Brew onboarding flow",
"type": "signup",
"category": "welcome",
"categoryLabel": "Welcome",
"emailCount": 6,
"spanDays": 14,
"remixCount": 12,
"previewImages": [
"https://cdn.brew.new/email-preview-brew-1.png",
"https://cdn.brew.new/email-preview-brew-2.png",
"https://cdn.brew.new/email-preview-brew-3.png"
],
"publishedAt": "2026-09-01T12:00:00.000Z",
"updatedAt": "2026-09-01T12:00:00.000Z",
"anchor": "signedUpAt",
"steps": [
{
"order": 1,
"dayOffset": 0,
"delayDays": 0,
"subject": "Welcome to Brew",
"previewText": "Here’s how to set up your first brand.",
"category": "welcome",
"categoryLabel": "Welcome",
"emailId": "pt1_k97nvhqe6xgyj67g58ajwj1tj58egexx",
"previewImage": "https://cdn.brew.new/email-preview-brew-1.png"
},
{
"order": 2,
"dayOffset": 2.1,
"delayDays": 2.1,
"subject": "Three templates to try today",
"category": "education",
"categoryLabel": "Education",
"emailId": "pt1_k97s409kdrzbeajqffq6011wfn8egmdq",
"previewImage": "https://cdn.brew.new/email-preview-brew-2.png"
}
]
}Get a flow
One public flow as the bare row, with anchor (what day 0 means) and every step’s subject, previewText, dayOffset, delayDays, category, previewImage and emailId. Organization-wide.
Use when reading a sequence in full before remixing it, or fetching each step’s rendered body.
Input slug in the path: the brand domain from a listFlows card (case-insensitive). include=html adds each step’s rendered HTML, best-effort per step: a step whose body is no longer servable comes back without html rather than failing the flow.
Returns 200 with the flow. A step’s emailId is a template reference: pass it as referenceEmailId on POST /v1/emails; for the body itself use include=html here (GET /v1/templates lists the gallery and takes no id).
Errors 404 FLOW_NOT_FOUND when the flow is unknown, private, or a step’s template was taken down (the anonymous read fails closed as a whole).
See also listFlows, generateEmail.
curl --request GET \
--url https://brew.new/api/v1/flows/{slug} \
--header 'Authorization: Bearer <token>'import requests
url = "https://brew.new/api/v1/flows/{slug}"
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/flows/{slug}', 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/flows/{slug}",
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/flows/{slug}"
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/flows/{slug}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://brew.new/api/v1/flows/{slug}")
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{
"slug": "brew.new",
"brand": {
"name": "Brew",
"logo": "https://cdn.brew.new/brand/fetched-logo/brew.new/logo.png"
},
"title": "Brew onboarding flow",
"type": "signup",
"category": "welcome",
"categoryLabel": "Welcome",
"emailCount": 6,
"spanDays": 14,
"remixCount": 12,
"previewImages": [
"https://cdn.brew.new/email-preview-brew-1.png",
"https://cdn.brew.new/email-preview-brew-2.png",
"https://cdn.brew.new/email-preview-brew-3.png"
],
"publishedAt": "2026-09-01T12:00:00.000Z",
"updatedAt": "2026-09-01T12:00:00.000Z",
"anchor": "signedUpAt",
"steps": [
{
"order": 1,
"dayOffset": 0,
"delayDays": 0,
"subject": "Welcome to Brew",
"previewText": "Here’s how to set up your first brand.",
"category": "welcome",
"categoryLabel": "Welcome",
"emailId": "pt1_k97nvhqe6xgyj67g58ajwj1tj58egexx",
"previewImage": "https://cdn.brew.new/email-preview-brew-1.png"
},
{
"order": 2,
"dayOffset": 2.1,
"delayDays": 2.1,
"subject": "Three templates to try today",
"category": "education",
"categoryLabel": "Education",
"emailId": "pt1_k97s409kdrzbeajqffq6011wfn8egmdq",
"previewImage": "https://cdn.brew.new/email-preview-brew-2.png"
}
]
}Authorizations
Send your Brew API key as Authorization: Bearer brew_xxx.
Path Parameters
The flow’s brand domain, as returned in every GET /v1/flows row. Case-insensitive.
1 - 253"brew.new"
Query Parameters
Detail-only expansions, comma-separated. html adds each step’s rendered HTML. Rendered email is bulky — over MCP only the first step or two fit one response; the rest arrive without html and the summary says how many were kept. A step’s emailId is already a create_email_design reference, so reuse needs no body; for the bodies themselves call GET /v1/flows/{slug}?include=html over REST, which has no cap. Best-effort per step: a step whose body is no longer servable comes back without html rather than failing the flow.
Response
The flow, with anchor and every step.
1Show child attributes
Show child attributes
1newsletter, signup 11x >= 1x >= 0x >= 0submittedAt, signedUpAt, verifiedAt, firstEmail Show child attributes
Show child attributes
Was this page helpful?