Audience
Audiences (lists)
Group contacts into the audiences you send campaigns to.
An audience (list) is a named group of contacts. Campaigns and sequences target audiences.
/v1/lists/v1/lists/v1/lists/:id/v1/lists/:id/v1/lists/:id/v1/lists/:id/contacts/v1/lists/:id/contacts/v1/lists/:id/contacts/:contactId/v1/lists/:id/tagsconst list = await mail.lists.create({ name: "Newsletter" });
await mail.lists.addContacts(list.id, ["ada@example.com", "grace@example.com"]);Audiences that describe themselves
An audience can hold a rule instead of a membership. Give it a filter and it stops being a list you maintain and becomes a question your contacts answer: everyone on a free plan who never finished onboarding, everyone dormant a month, everyone in a trial ending this week. Members are whoever matches right now, so it stays correct on its own — you never recompute it and push tags back in.
This pairs with syncing your app's users. POST /v1/contacts upserts by email, so push whatever your product knows — plan, signup date, last active — onto a contact's metadata, then segment on those traits as trait:<key>.
/v1/lists/v1/lists/:id/v1/lists/preview-segment// 1. Push what your app knows onto the contact (upserts by email).
await mail.contacts.create({
email: "ada@example.com",
metadata: { plan: "free", onboarded: false, signed_up_at: "2026-07-01" },
});
// 2. Check the rule BEFORE you build anything on it.
const { size } = await mail.lists.previewSegment({
match: "all",
conditions: [
{ field: "trait:plan", op: "eq", value: "free" },
{ field: "trait:onboarded", op: "eq", value: "false" },
],
});
console.log("this reaches " + size + " people");
// 3. Save it as an audience you can send to.
const audience = await mail.lists.create({
name: "Trials that never started",
filter: {
match: "all",
conditions: [
{ field: "trait:plan", op: "eq", value: "free" },
{ field: "trait:onboarded", op: "eq", value: "false" },
],
},
});Fields: tag, stage, status, email, name, created_at, updated_at, and any synced trait as trait:<key>. Operators: eq, neq, contains, exists, not_exists, before, after. Match all (default) or any. A rule may hold up to 25 conditions.
preview-segment is there so that never happens quietly.Growing an audience (public signup)
Enable signup on an audience and it grows itself: every audience gets a hosted, branded signup page plus an embeddable HTML form for your own site. Double opt-in (default) sends a confirmation email from your verified sender; the signup tag is applied to every subscriber — a sequence triggered by that tag is your welcome automation. Signups that arrive while you're at your contact limit are waitlisted (never lost) and admitted automatically when room frees up.
/v1/lists/:id/v1/subscribe/v1/lists/:id/growth<!-- Drop this on your site — style it however you like -->
<form action="https://api.rootmail.io/v1/subscribe" method="post">
<input type="hidden" name="list_id" value="lst_your_audience">
<input type="email" name="email" placeholder="you@example.com" required>
<input type="text" name="name" placeholder="Your name">
<input type="text" name="website" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Subscribe</button>
</form>website field is a honeypot — leave it in. Bots fill it; humans never see it.