BitelioBitelio

Segments

Build named audiences of contacts, either rule-driven or hand-picked

A segment is a named group of contacts you can point campaigns at or use to kick off workflows. Segments come in two flavours: Dynamic and Static.

Dynamic vs Static

DynamicStatic
MembershipDerived live from filter conditionsHand-picked — you choose every member
condition fieldRequired — holds the filter definitionMust be omitted
Add/remove members via APINot possible (membership follows the filter)POST / DELETE /segments/:id/members
Membership recomputationRecalculated in the background when tracking is onN/A — changes only through explicit API calls
Entry/exit eventsEmitted only with Track membership changes turned onNever emitted by add/remove calls
Updating the filterTriggers a member count recalculationcondition on an update is silently discarded

Reach for dynamic segments when membership should follow behaviour ("Pro-plan subscribers who opened any email in the past 14 days"). Reach for static segments when the list is curated by hand — beta testers, event attendees, or contacts pulled in from another system.

Filtering on a dynamic segment

Dynamic membership is driven by a filter: a set of conditions matched against every contact. Conditions can reference:

  • The built-in fields email, subscribed, createdAt, and updatedAt.
  • Any custom field you've saved on contacts (everything under data.*).
  • Events you've tracked through /v1/track (event.signed_up, event.purchased, and so on).
  • Engagement signals such as email.opened, email.clicked, and email.bounced.
  • Whether the contact belongs to some other segment.

Conditions combine with AND / OR and can be nested into groups, so audiences like "subscribed Pro users and (opened or clicked an email in the last 14 days)" are expressible.

Every available field, operator, and value type — with worked examples — is documented in the Segment filter reference.

Static segments

A static segment is a list you maintain yourself. Nothing joins or leaves it automatically; its membership is exactly what you've put in it.

Creating

In the dashboard, open Segments, hit Create Segment, and pick Static. If you like, seed it with initial members right away via the contact search.

Adding and removing members

Inside a static segment, the Add Members search finds contacts to include. It only surfaces contacts that already exist in the project — so there's no way to add a nonexistent one by mistake — and members already in the segment appear greyed out.

Via the API:

  • POST /segments/:id/members — add contacts by email. Body: { emails: string[], createMissing?: boolean, subscribed?: boolean }. Setting createMissing: true creates any missing contacts on the spot (subscribed by default, unless subscribed: false is passed). The response summarises { added, created, notFound }.
  • DELETE /segments/:id/members — remove contacts by email. Body: { emails: string[] }. Responds with { removed }.

These two endpoints work exclusively on static segments — pointing them at a dynamic one yields 400.

API-driven membership changes take effect at once, but they never emit entry/exit events; those exist only for dynamic segments with tracking enabled.

Tracking membership changes

A dynamic segment can enable Track membership changes. With it on, Bitelio emits an event each time a contact joins or leaves:

  • segment.<slug>.entry — contact joined
  • segment.<slug>.exit — contact left

Bitelio builds <slug> from the segment's name: everything lowercased, accents and punctuation removed, spaces turned into hyphens, and runs of hyphens collapsed to one. So "VIP Customers" yields segment.vip-customers.entry. Choose names whose slugs won't need to change — a rename means a new event name.

These events are a natural way to power workflows: greet contacts entering a "Trial users" segment, or win back those leaving "Active users". The payload format is documented under Webhooks.

How tracking works

Creating a dynamic segment or editing its filter refreshes the member count right away. From then on, membership is recomputed in the background at a regular interval: Bitelio diffs the current matches against the last known set, logs who entered and who left, and fires the matching events.

That background interval means the dashboard's memberCount can trail reality by a few minutes. When you need an up-to-date number, or want entry / exit events to fire without waiting:

  • POST /segments/:id/refresh — recount only (inexpensive, emits nothing).
  • POST /segments/:id/compute — run a complete membership recomputation, flushing any pending entry/exit events.

Using segments

Segments plug into two places:

  • As campaign audiences in email campaigns (point the campaign's audience at the segment)
  • As workflow triggers in marketing automation (listen for the segment.<slug>.entry event)

Performance notes

  • Date comparisons on data.* fields work by ordering ISO 8601 strings. To use within / olderThan on a custom date, store it as an ISO 8601 string (2026-05-06T12:00:00Z), not as a Unix timestamp.
  • Chaining many untracked dynamic segments inside each other makes evaluation expensive. When one segment is referenced by others, turn on Track membership for it — its member list is then read directly instead of being recomputed on every evaluation.
  • memberCount is a cache that may run a few minutes behind. Treat it as an estimate, and hit POST /segments/:id/refresh when an exact figure matters.

Deleting a segment

If a segment backs an active campaign (one in DRAFT, SCHEDULED, or SENDING), deleting it fails with 409 Conflict. Either cancel that campaign or switch its audience before removing the segment.

API reference

All segment endpoints — list, get, create, update, delete, list members, add/remove static members, refresh count, and compute membership — are catalogued in the API overview.

What's next