Skip to main content
POST
Create Segment
Create a segment from either the legacy flat filter array or a nested root filter group. You must provide exactly one of filters or root, and it must contain at least one filter.

Request

string
required
Segment name.
FilterLeaf[]
Legacy v1 filter array. Use with filterJoinOperator.
string
default:"and"
and requires every v1 filter to match. or matches any v1 filter.
FilterGroup
Nested v2 filter group. Use this for nested AND/OR logic, event filters, or segment filters. Groups need kind: "group" and a children array. Filters need field, operator and a string value; omit value only for is_empty and is_not_empty. A child without kind is read as a filter.
A segment filter matches the members of another saved segment. Counting follows up to 16 levels of segment-to-segment references and 1,000 references in total; past either limit, counting the segment returns SEGMENT_REFERENCE_DEPTH_EXCEEDED or SEGMENT_REFERENCE_COUNT_EXCEEDED. Stripe trial subfilters stay under field: "stripeTrialProduct": prod_123:is_canceled, prod_123:end_at:2026-05-26, or prod_123:start_at:7 days ago. Every filter field validates its own operator set:
  • status, segment, smsStatus: is, is_not
  • phone: is_empty, is_not_empty
  • tag: contains, not_contains, is_empty, is_not_empty
  • email: contains, not_contains (domain or substring), is, is_not (exact, case-insensitive address)
  • emailProvider, list: is, is_not, is_empty, is_not_empty
  • firstName, lastName: contains, not_contains, is_empty, is_not_empty
  • added: less_than, more_than
  • attribute: equality, empty checks, numeric/date comparisons, and contains checks
  • event, email engagement fields: is, is_not, at_least, less_than_count
  • emailBounced: also supports is_temporary_bounce, is_permanent_bounce
  • Stripe product fields: product-specific purchase/current/trial/date operators
  • commerceProduct, commerceCollection: is, is_not, at_least, less_than_count
For smsStatus, use subscribed, unsubscribed, pending, or not_subscribed. Phone presence filters use an empty value string. Commerce values use provider:productId or provider:collectionKey, for example shopify:42 or shopify:summer. Count operators append an order threshold, for example shopify:42:3; omitting the threshold means 1. A bare product ID or collection key matches across providers. Prefer provider-qualified values to avoid collisions between stores. Email engagement values can target any email (24h, 30d, all; hour windows accept whole hours from 1h to 8760h), one campaign (campaign:<campaign_id>), or a delivery policy. Use marketing:<timeRange> for marketing-policy campaigns, automations, and Send API traffic, and transactional:<timeRange> for transactional sends. For example, {"field":"emailOpened","operator":"is","value":"marketing:all"} matches contacts who have ever opened a marketing email. Policy scopes work with presence and bounce-subtype operators, not count operators. Attribute filter names are matched case-sensitively against synced subscriber attributes. When a filter references a custom attribute no subscriber has a synced value for, the segment is still created but the response includes a warnings array explaining that the filter currently matches no subscribers (or every subscriber for exclusion operators like is_empty), with a casing suggestion when a close match exists. For arrays of objects, use wildcard paths such as history_events[].eventvenue_id:2103. Two or more positive attribute filters on the same array path that are connected only by AND must be satisfied by one shared array element. A venue match on one history entry cannot combine with a date match on another entry. Negative filters (is_not, not_contains, and is_empty) remain independent because each asserts that no array element matches its condition.

Responses