Segments
Group and target your contacts with dynamic or static segments
Segments let you create named groups of contacts that can be targeted in campaigns and used as triggers in workflows. There are two types: Dynamic and Static.
Dynamic vs Static
| Dynamic | Static | |
|---|---|---|
| Membership | Computed from filter conditions in real time | Manually curated — you decide who is in |
condition field | Required — describes the filters | Must be omitted |
| Add/remove members via API | Not allowed (the filter decides) | POST / DELETE /segments/:id/members |
| Membership recomputation | Re-evaluated in the background when tracked | N/A — membership only changes when you call the API |
| Entry/exit events | Fired only when Track membership changes is enabled | Not fired by add/remove API calls |
| Updating the filter | Member count is recomputed | condition is silently ignored on update |
Use dynamic segments for behavioural targeting ("subscribed users on the Pro plan who opened any email in the last 14 days"). Use static segments for one-off curated lists like beta testers, conference attendees, or contacts imported from an external system.
Filtering on a dynamic segment
A dynamic segment's membership is defined by a filter — a set of conditions evaluated against your contacts. You can filter on:
- Built-in contact fields:
email,subscribed,createdAt,updatedAt. - Custom fields you've stored on contacts (anything under
data.*). - Custom events tracked via
/v1/track(event.signed_up,event.purchased, etc.). - Email engagement (
email.opened,email.clicked,email.bounced, etc.). - Membership of another segment.
Filters can be combined with AND or OR and nested into groups for more complex audiences — for example "subscribed Pro users and (opened or clicked an email in the last 14 days)".
For the full list of fields, operators, and value types — plus worked examples — see the Segment filter reference.
Static segments
Static segments are manually curated lists. Membership doesn't change automatically — you decide exactly who is in.
Creating
Go to Segments in the dashboard and click Create Segment, then choose Static. You can optionally add initial members straight away using the contact search.
Adding and removing members
Open a static segment and use the Add Members search to find contacts. The search looks up contacts already in your project, so you can't accidentally add someone who doesn't exist. Contacts already in the segment are greyed out.
Programmatically, use:
POST /segments/:id/members— add contacts by email. Body:{ emails: string[], createMissing?: boolean, subscribed?: boolean }. WithcreateMissing: true, contacts that don't exist yet are created (and start subscribed unless you passsubscribed: false). The response reports{ added, created, notFound }.DELETE /segments/:id/members— remove contacts by email. Body:{ emails: string[] }. Returns{ removed }.
Both endpoints only accept static segments. Calling them on a dynamic segment returns 400.
Membership changes via these API calls are immediate but do not fire entry/exit events — those are reserved for dynamic, tracked segments.
Tracking membership changes
Dynamic segments can opt into Track membership changes. When enabled, Plunk fires events whenever a contact enters or leaves the segment:
segment.<slug>.entry— contact joinedsegment.<slug>.exit— contact left
The <slug> is derived from the segment name: lowercased, accents and punctuation stripped, whitespace replaced with hyphens, repeated hyphens collapsed. "VIP Customers" becomes segment.vip-customers.entry. Pick segment names that produce stable slugs — renaming a segment changes the event name.
Use these events to drive workflows (welcome a contact when they enter a "Trial users" segment, send a re-engagement email when they exit "Active users", etc.). See Webhooks for the payload format.
How tracking works
The member count updates immediately when you create or change a dynamic segment's filter. After that, Plunk recomputes membership in the background on a regular cadence — diffing current matches against the previous set, recording entries and exits, and emitting the corresponding events.
Because of this background cadence, the memberCount shown in the dashboard can lag the live state by a few minutes. If you need a fresh value or want to drive a workflow off entry / exit immediately:
POST /segments/:id/refresh— force a count refresh (cheap, no events).POST /segments/:id/compute— force a full membership recomputation, which fires any pending entry/exit events.
Using segments
Segments can be used to:
- Target contacts in email campaigns (set the campaign audience to a segment)
- Trigger workflows in marketing automation (use the
segment.<slug>.entryevent)
Performance notes
- Date filters on
data.*rely on ISO 8601 string ordering — store dates as ISO 8601 strings (2026-05-06T12:00:00Z) rather than Unix timestamps if you want to usewithin/olderThanon them. - Nesting many untracked dynamic segments inside one another increases evaluation cost. If a segment is referenced by others, enable Track membership on it so its members are looked up directly instead of recomputed each time.
- The cached
memberCountmay be a few minutes behind reality. Treat it as approximate; usePOST /segments/:id/refreshto force a refresh if you need an exact count.
Deleting a segment
Deleting a segment that's referenced by an active campaign (in DRAFT, SCHEDULED, or SENDING state) returns 409 Conflict. Cancel the campaign or pick a different audience first.
API reference
See the segments API endpoints in the API overview — list, get, create, update, delete, list members, add/remove static members, refresh count, and compute membership.