BitelioBitelio

Segment filter reference

The filter syntax shared by dynamic segments, filtered campaign audiences, and workflow conditions

One filter format shows up in three places: dynamic segments, campaign audiences with audienceType: "FILTERED", and CONDITION steps inside workflows. Master it once and it carries over everywhere.

If you'd rather start with concepts than syntax, read the Segments concept page first.

How a filter is structured

Every filter consists of a top-level connector (AND or OR) plus a list of groups. Within a group, all conditions are joined with AND; the top-level connector then combines the groups.

An example makes it concrete: "subscribed users and on the Pro plan and (opened or clicked an email recently)".

{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "subscribed", "operator": "equals", "value": true },
        { "field": "data.plan",  "operator": "equals", "value": "pro" }
      ]
    },
    {
      "filters": [],
      "conditions": {
        "logic": "OR",
        "groups": [
          { "filters": [{ "field": "email.opened",  "operator": "triggeredWithin", "value": 14, "unit": "days" }] },
          { "filters": [{ "field": "email.clicked", "operator": "triggeredWithin", "value": 14, "unit": "days" }] }
        ]
      }
    }
  ]
}

Nesting works by giving a group its own conditions — that's how you express "this AND (that OR this)" without collapsing the logic into one level. When you work in the dashboard, the segment builder assembles all of this visually.

Fields you can filter on

Each field value carries a namespace prefix that tells Bitelio which aspect of the contact the condition targets.

Field patternTargetsExamples
emailThe contact's email addressemail
subscribedThe contact's subscription statesubscribed
createdAt, updatedAtBuilt-in contact timestampscreatedAt
data.<path>Custom contact data — supports nested pathsdata.plan, data.profile.tier
event.<eventName>Custom events tracked via /v1/trackevent.signed_up
email.<activity>Email engagement: sent, delivered, opened, clicked, bounced, complainedemail.opened
segment.<segmentId>Membership of another segmentsegment.cuid_of_other_segment

Operators

Which operators apply depends on the kind of field you're filtering.

Text fields

For email and any data.<key> that holds a string.

OperatorWhat it does
equalsExact match — ignores case on email, case-sensitive on data.*.
notEqualsThe inverse of equals.
containsSubstring match, ignoring case.
notContainsThe inverse of contains.

Yes/no fields

For subscribed and any data.<key> that holds true or false.

OperatorWhat it does
equalsMatch true or false.
notEqualsThe inverse.

Dates and timestamps

For createdAt, updatedAt, and any data.<key> that holds an ISO 8601 date string.

OperatorWhat it does
equals / notEqualsTimestamp match. A date-only value (YYYY-MM-DD) matches anywhere within that UTC day.
greaterThan / lessThanStrictly after / strictly before.
greaterThanOrEqual / lessThanOrEqualThe inclusive versions.
withinFalls inside the last N units. Requires unit: "days" / "hours" / "minutes".
olderThanLies more than N units in the past. Requires unit.

On custom date fields (data.<key>), within and olderThan require the value to be stored as an ISO 8601 string (e.g. "2026-05-06T12:00:00Z"). Unix timestamps or other formats will compare incorrectly.

Numbers

Any numeric data.<key> supports: equals, notEquals, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual. No unit is involved.

Field existence

Works on any data.<key>, whatever its value type.

OperatorWhat it does
existsThe key is set on the contact with a non-null value.
notExistsThe key is absent, or explicitly null.

Events and email activity

The same operator set serves both event.<eventName> (custom events) and email.<activity> (email engagement).

OperatorWhat it does
triggeredThe event has occurred for this contact at least once, at any point.
notTriggeredThe event has never occurred for this contact.
triggeredWithinOccurred at least once within the last N units. Requires unit.
triggeredOlderThanHas occurred, but not within the last N units. Requires unit.
notTriggeredWithinNo occurrence in the last N units — contacts who never triggered it also match. Requires unit.

Segment membership

For segment.<segmentId>, where <segmentId> is the ID of another segment in your project.

OperatorWhat it does
memberOfSegmentThe contact currently belongs to the referenced segment.
notMemberOfSegmentThe contact does not belong to it.

Quick reference: what to pass with each operator

  • Take a value: equals, notEquals, contains, notContains, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual, within, olderThan, triggeredWithin, triggeredOlderThan, notTriggeredWithin.
  • Take a unit ("days", "hours", or "minutes"): within, olderThan, triggeredWithin, triggeredOlderThan, notTriggeredWithin.
  • Take nothing else: exists, notExists, triggered, notTriggered, memberOfSegment, notMemberOfSegment.

Examples

Engaged users on the Pro plan

Subscribed Pro-plan users who opened or clicked any email in the last 14 days but haven't clicked anything in the last 30 days.

{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "subscribed", "operator": "equals", "value": true },
        { "field": "data.plan",  "operator": "equals", "value": "pro" }
      ]
    },
    {
      "filters": [],
      "conditions": {
        "logic": "OR",
        "groups": [
          { "filters": [{ "field": "email.opened",  "operator": "triggeredWithin", "value": 14, "unit": "days" }] },
          { "filters": [{ "field": "email.clicked", "operator": "triggeredWithin", "value": 14, "unit": "days" }] }
        ]
      }
    },
    {
      "filters": [
        { "field": "email.clicked", "operator": "notTriggeredWithin", "value": 30, "unit": "days" }
      ]
    }
  ]
}

New trial users without a purchase

Subscribed contacts created in the last 7 days who haven't yet triggered a purchase event.

{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "subscribed",     "operator": "equals",       "value": true },
        { "field": "createdAt",      "operator": "within",       "value": 7, "unit": "days" },
        { "field": "event.purchase", "operator": "notTriggered" }
      ]
    }
  ]
}

Power users above a tier

Members of the power-users segment whose lifetime value is at least 500.

{
  "logic": "AND",
  "groups": [
    {
      "filters": [
        { "field": "segment.<powerUsersSegmentId>", "operator": "memberOfSegment" },
        { "field": "data.lifetimeValue", "operator": "greaterThanOrEqual", "value": 500 }
      ]
    }
  ]
}