Playbook · Segments
Resend Contacts and Segments — who gets the Broadcast
Create Contacts and Segments, then pass a segment id into your Broadcast draft. Audiences are deprecated.
2026-10-16
How this differs from sibling playbooks
This page owns who is on the list. Resend bilingual newsletter owns domain, signup copy, and the Dashboard-first path. Resend Broadcast drafts owns the draft and the STOP before Send. This page does not create or send a Broadcast.
| Playbook | Owns |
|---|---|
| Resend bilingual newsletter | Domain verify, Dashboard-first Broadcasts, signup copy, bilingual Topic strategy, first Send gates |
| Resend Broadcast drafts | POST /broadcasts draft + STOP before Send (send: false / Dashboard Send) |
| Cancel or duplicate a Broadcast | Cancel scheduled / Duplicate after a draft exists |
| This page | Contacts + Segments CRUD so Broadcast targeting is safe and intentional — Audiences → Segments migration |
Who it’s for / not for
| For | Not for |
|---|---|
| People who already (or will) run the StackQuay newsletter on Resend | Cold / purchased / scraped lists — STOP; consent required (human must verify PDPO / local rules) |
| An agent can create a Segment and add opted-in Contacts; you write the consent line and press Send | Teams still coding against Audiences-only endpoints without a migration plan (Audiences are deprecated) |
Operators who need a clean segment_id before calling Broadcast create with send: false | Anyone treating this as PDPO / GDPR legal advice or promising deliverability ROI |
Stack (spine only)
Secondary (later): Contact properties API, Contact imports, Automations “Add to Segment”, MCP / CLI deep-dive, suppression list ops.
- Global Contacts — one email = one Contact across the team (Contacts intro)
- Segments API — internal groups; Contacts never see Segment names (manage Segments).
POST /segmentscreate,GET /segmentslist,PATCH /segments/:idrename,DELETE /segments/:iddelete,GET /segments/:id/contactslist members - Contacts API —
POST /contactscreate;POST /contacts/:id|email/segments/:segmentIdadd;DELETEthe same path to remove - Topics (mention only) — recipient-facing prefs; pair with Segments when you Send
- Audiences API — deprecated; still works for now and will be removed. Prefer Segments (create Audience, migration)
Bot vs human
| Bot does | Human must do |
|---|---|
Propose Segment names (playbook-subscribers, zh-readers, …) | Own the Resend account and API key in env (never paste re_… into chat or git) |
| Call Segments create / list / rename; create Contacts with opt-in-only emails you already approved | Confirm consent source (marketing checkbox unchecked by default — Resend consent KB) |
| Add or remove a Contact on a Segment after you have checked the list | Record opt-in; honor global unsubscribed and Topics prefs |
Hand segment_id to the Broadcast draft playbook; never send: true | Press Send only via the human-gate playbook |
| Flag Audiences deprecation if old code appears | Dashboard spot-check Segment size before the first live Broadcast |
| Never import purchased CSVs or invent addresses | PDPO / privacy policy / unsubscribe UX (not legal advice) |
Numbered steps
- Prerequisites. Verified sending domain and an API key in env you control (docs). Signup and consent language come from Resend bilingual newsletter. Human must verify DNS, that the key is not in the repo, and that you are not building a cold-email list.
- Mental model (Nov 2025+ Global Contacts) (migration). Before: the same email in two Audiences was two Contact objects. Now: a Contact is global; a Segment is an internal group; a Contact can be in zero, one, or many Segments. A Topic is what kind of mail (user prefs); a Segment is who you intend to target. A Contact must be in a Segment to receive a Broadcast. If
unsubscribed: trueor on the Suppression List, Resend will not send even if Segment membership exists. - Create a Segment.
POST https://api.resend.com/segmentswith{ "name": "…" }(create-segment). Names you can change:playbook-subscribers(main list) andplaybook-preview(you and testers). The response returnsidandname. Sketch — do not run with a live key in chat:resend.segments.create({ name: 'playbook-subscribers' }).data.idis thesegment_idfor a later Broadcast draft. - List / rename / delete. List:
GET /segments. Rename:PATCH /segments/:idwith a newname. Delete:DELETE /segments/:id— does not delete Contacts; it only removes Segment membership. Human must verify before delete if any scheduled Broadcast still targets that Segment. - Create Contacts (opt-in only).
POST /contactswith at leastemail; optionalfirst_name,last_name,unsubscribed,segments, and topic subscriptions (create-contact). STOP: only add addresses that actively opted in (consent KB). Pre-checked ToS clauses and assumed opt-in are not valid permission per that guide. Sketch:resend.contacts.create({ email, firstName, unsubscribed: false }). - Add / remove Contact ↔ Segment. Resend says you do not need separate consent to move someone between Segments once they are a Contact — you still needed consent to email them at all. For this hub, only Segment people who opted into the newsletter. Add:
POST /contacts/:contactId/segments/:segmentIdor the email form of that path. Remove:DELETEthe same path. List members:GET /segments/:segmentId/contacts. You can list members for a check; you confirm before a Broadcast. - Hand off to the Broadcast human-gate. Pass the verified
segment_idinto Resend Broadcast drafts withsendomitted orfalse. Optionaltopic_idso prefs are respected. This playbook does not create or send Broadcasts. - If you still have Audiences code. Those endpoints are deprecated. Migrate to Segments and global Contacts. Prefer Topics for unsubscribe granularity; keep Segments for internal targeting.
Failure modes / HK caveats
- Spam / purchased lists — STOP. High complaint rates can pause accounts. Not PDPO legal advice.
- Secrets in chat/git — any
re_key in markdown or agent logs → rotate. Env only. - Wrong Segment on a Broadcast — preview vs full list. List contacts and check the Dashboard count first.
- Audiences vs Segments drift — new work uses
/segmentsonly. - Delete Segment ≠ delete people — Contacts remain.
- Global unsubscribe / suppression — adding to a Segment does not override
unsubscribedor the Suppression List. - Bot must not Send.
- Keep Contact properties to what the person opted into.
Newsletter CTA
The path: opt-in, then a Segment, then a Broadcast draft, then you send.
Human must verify
- Consent wording on signup (unchecked, specific) and a privacy notice for HK readers.
- API key storage (env only); no keys in chat, queue markdown, or git.
- Segment naming, and which Segment is preview vs live subscribers.
- Every Contact added via an agent came from a real opt-in source you can point to.
- Dashboard count matches
GET /segments/:id/contactsbefore the first Broadcast. - Topics strategy (if any) aligned with unsubscribe prefs.
- No Audiences-only code left on the production signup path.
- You press Send on a Broadcast (other playbook).
- PDPO / retention: not certified here — escalate if you collect more than email and name.
Doc gaps
Exact contact quotas and plan limits are not frozen here (check Billing). Contact Import API and Automations “Add to Segment” are not stepped. The MCP/CLI matrix is deferred. HK PDPO is outside Resend docs — confirm with counsel if you need to. Not legal advice.
Docs cited
- Contacts introduction · 2026-10-16
- Managing Segments · 2026-10-16
- Migrating from Audiences to Segments · 2026-10-16
- Create Segment · 2026-10-16
- Create Contact · 2026-10-16
- Add Contact to a Segment · 2026-10-16
- Create Audience (deprecated) · 2026-10-16
- What counts as email consent? · 2026-10-16