Segments
Save filters over your contacts, list who matches, and follow tracked segments over time.
Create a segment
Creates a segment: a saved filter over the workspace’s contacts. Requires an API key with the full scope.
A segment holds the contacts from its source (the subscribers of audience_ids, or every contact when it’s empty) that match its conditions. Membership is evaluated live each time the segment is counted, listed, previewed or used by a campaign that sends. See Segments.
Each plan includes a number of segments per workspace, tracked or not. See Limits.
/segmentsBody parameters
namestringrequireddescriptionstring | nullaudience_idsstring[]aud_…) in this workspace, up to 100. The segment only holds contacts subscribed to at least one of them. Empty or omitted means every contact in the workspace.conditionsobjecttrackedbooleandefault: falseConditions
conditions holds groups of rules. The top-level match joins the groups, and each group’s match joins its rules:
{
"match": "all",
"groups": [
{ "match": "any", "rules": [{ "field": "email_domain", "operator": "in", "value": ["acme.com", "globex.io"] }] },
{ "match": "all", "rules": [{ "field": "status", "operator": "equals", "value": "subscribed" }] }
]
}matchisall(default) orany, on the top level and in each group.- Omit
conditions, or send no groups, to include everyone from the source. Empty groups are dropped. - The flat shape
{ "match": "any", "rules": [...] }is also accepted and stored as one group. - A segment can have up to 10 groups and 50 rules in total.
Fields
| Field | Type | Notes |
|---|---|---|
email |
string | |
email_domain |
string | The part of the address after @. |
first_name, last_name |
string | |
status |
enum | subscribed (not globally unsubscribed and subscribed to at least one audience, so campaigns can reach the contact) or unsubscribed. Operators: equals, not_equals. |
created_at, updated_at |
datetime | When the contact was created or last changed, compared in UTC. |
audience |
audience | Subscribed membership. in matches contacts subscribed to any of the audience IDs, not_in matches contacts subscribed to none of them. |
tags |
tags | The contact’s tags. Values are compared in lowercase. |
score |
score | The contact’s lead score. |
custom_fields.<key> |
depends on the field | Text fields are string, number fields number, date fields date (YYYY-MM-DD), boolean fields boolean, select fields enum and multi-select fields multi. |
orders_count, total_spent, average_order_value |
metric | From the contact’s orders. 0 for contacts without orders. Amounts are in the contact’s order currency. |
first_order_at, last_order_at |
moment | Unset for contacts without orders. |
expected_next_order_at |
moment | The last order plus the contact’s average gap between orders. Set from the second order on, and can be in the future. |
churn_risk |
enum | low, medium or high: time since the last order compared with the contact’s usual gap (at least 14 days), or with 90 days for one-time buyers. Unset without orders. |
last_active_at |
moment | The last time the tracking script saw the contact on your site. |
purchased |
purchase | Orders, see Activity rules. |
viewed_product |
view | Product views recorded by the tracking script. |
cart |
cart | Open and abandoned carts. |
used_coupon |
coupon | Orders that used a coupon code. |
campaign_activity |
campaign_activity | Campaign emails received, opened or clicked. |
List segment fields returns the fields of your workspace, including its custom fields and audiences, with the operators each one accepts.
Operators
| Type | Operators |
|---|---|
| string | equals, not_equals, contains, not_contains, starts_with, ends_with, in, not_in, is_set, is_not_set |
| number | equals, not_equals, greater_than, greater_than_or_equal, less_than, less_than_or_equal, between, is_set, is_not_set |
| date | on, before, after, between, in_last_days, more_than_days_ago, in_next_days, is_set, is_not_set |
| datetime | on, before, after, between, in_last_days, more_than_days_ago |
| boolean | is_true, is_false, is_set, is_not_set |
| enum | in, not_in, is_set, is_not_set |
| multi | in (has any of), contains_all (has all of), not_in (has none of), is_set, is_not_set |
| audience | in, not_in |
| tags | in (has any of), contains_all (has all of), not_in (has none of), is_set (has any tag), is_not_set (has no tags) |
| score | equals, not_equals, greater_than, greater_than_or_equal, less_than, less_than_or_equal, between |
| metric | equals, not_equals, greater_than, greater_than_or_equal, less_than, less_than_or_equal, between |
| moment | on, before, after, between, in_last_days, more_than_days_ago, in_next_days, is_set, is_not_set |
| purchase, view, coupon | has, has_not |
| cart | has_open_cart, has_abandoned_cart, has_no_open_cart |
| campaign_activity | received, not_received, opened, not_opened, clicked, not_clicked, received_not_opened, received_not_clicked |
Values
- Text comparisons on string fields ignore case. Select and multi-select values must match exactly.
not_equals,not_containsandnot_inalso match contacts that have no value.in,not_inandcontains_alltake a list of up to 100 values. Text values can be up to 500 characters.betweentakes[from, to], both included: two numbers or twoYYYY-MM-DDdates.on,beforeandaftertake aYYYY-MM-DDdate.beforeandafterdon’t include that day.in_last_days,more_than_days_agoandin_next_daystake a whole number of days from 1 to 3650, counted from the moment the segment is evaluated. Date custom fields compare calendar days in UTC;created_atandupdated_atuse exact times, soin_last_dayswith7means the last 7 × 24 hours.is_set,is_not_set,is_trueandis_falsetake no value.is_truematchestrue,1,yesandon;is_falsematchesfalse,0,noandoff.- A saved rule that no longer applies, for example after its custom field changed type, matches no contacts. Rules on a deleted custom field keep working from the values contacts still have, but new rules must use an existing field.
Activity rules
purchased, viewed_product, cart, used_coupon and campaign_activity take an object as value. Every key is optional.
| Field | Value keys |
|---|---|
purchased |
days: only orders placed in the last N days. product_ids: orders with any of these products (your shop’s product IDs). categories: orders with a product in any of these categories. min_count: at least this many matching orders (default 1, up to 1000). Canceled orders don’t count. |
viewed_product |
days, product_ids, categories and min_count as above, counting product views. |
cart |
days with has_abandoned_cart only: carts abandoned in the last N days. has_open_cart matches an active cart, has_no_open_cart matches contacts with no active or abandoned cart. |
used_coupon |
days, and coupon: the key of one coupon. Without coupon, any code counts. |
campaign_activity |
campaign_id: one campaign (cmp_...), any campaign when absent. days: only the last N days, all time when absent. |
days is a whole number from 1 to 3650. has_not is the opposite of has with the same value.
{
"match": "all",
"groups": [
{ "match": "all", "rules": [
{ "field": "purchased", "operator": "has", "value": { "categories": ["Shoes"], "days": 180 } },
{ "field": "churn_risk", "operator": "in", "value": ["medium", "high"] },
{ "field": "campaign_activity", "operator": "clicked", "value": { "days": 90 } }
] }
]
}received_not_opened and received_not_clicked match contacts who got at least one matching campaign email and opened or clicked none of them. Opens are approximate: Apple Mail loads images for every email it receives.
Returns
Returns 201 Created with the segment object, including contacts_count and subscribed_count. A new tracked segment starts with tracking.status set to syncing while Emailit records its current members.
| Status | When |
|---|---|
400 |
name is missing, or a field has the wrong type. |
403 |
tracked is true and the plan doesn’t include tracked segments. The body is {"error": "plan_required", "required_plan": "pro", ...}. |
422 |
A field or rule is invalid: errors is keyed by its path, such as conditions.groups.0.rules.1.value, and message repeats the first problem. Also returned when the workspace has reached its plan’s segment limit; that body includes usage.used and usage.limit. |
{
"object": "segment",
"id": "seg_2nYs9Kd1Lq3vB8wXcE4fT7uRm0p",
"name": "Pro customers renewing soon",
"description": null,
"audience_ids": ["aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a"],
"conditions": {
"match": "all",
"groups": [
{
"match": "all",
"rules": [
{ "field": "custom_fields.plan", "operator": "in", "value": ["pro", "enterprise"] },
{ "field": "custom_fields.renews_on", "operator": "in_next_days", "value": 30 }
]
}
]
},
"tracked": true,
"tracking": {
"status": "syncing",
"synced_at": null
},
"contacts_count": 412,
"subscribed_count": 398,
"created_at": "2026-10-18T12:00:00.000000+00:00",
"updated_at": "2026-10-18T12:00:00.000000+00:00"
}{
"error": "plan_required",
"message": "Tracked segments are included with Pro and Business.",
"required_plan": "pro"
}{
"message": "Validation failed. conditions.groups.0.rules.1.value: Enter a whole number of days between 1 and 3650.",
"errors": {
"conditions.groups.0.rules.1.value": [
"Enter a whole number of days between 1 and 3650."
]
}
}{
"error": "Pay as you go includes 3 segments.",
"message": "Pay as you go includes 3 segments.",
"usage": {
"used": 3,
"limit": 3
}
}Retrieve a segment
Retrieves a segment and counts its contacts at the moment you call it. Requires an API key with the full scope.
/segments/{id}Path parameters
idstringrequiredseg_…).Returns
Returns the segment object.
objectstringsegment.idstringseg_.namestringdescriptionstring | nullaudience_idsstring[]conditionsobject{ "match", "groups": [{ "match", "rules": [...] }] }. See Create a segment.trackedbooleantrackingobject | nullnull for segments that aren’t tracked. For tracked segments:
status:activewhen members are kept up to date,syncingwhile Emailit records the current members after the segment was created or tracking resumed, orpausedwhen the workspace’s plan no longer includes tracked segments.synced_at: when the whole segment was last compared with its rules, ornullbefore the first comparison.
contacts_countintegersubscribed_countintegercontacts_count that campaigns can send to: contacts that aren’t globally unsubscribed and are subscribed to at least one audience. Suppressed addresses are still counted.created_at, updated_atstringReturns 404 if the segment doesn’t exist.
{
"object": "segment",
"id": "seg_2nYs9Kd1Lq3vB8wXcE4fT7uRm0p",
"name": "Pro customers renewing soon",
"description": "Pro and Enterprise plans that renew in the next 30 days.",
"audience_ids": ["aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a"],
"conditions": {
"match": "all",
"groups": [
{
"match": "all",
"rules": [
{ "field": "custom_fields.plan", "operator": "in", "value": ["pro", "enterprise"] },
{ "field": "custom_fields.renews_on", "operator": "in_next_days", "value": 30 }
]
}
]
},
"tracked": true,
"tracking": {
"status": "active",
"synced_at": "2026-10-18T00:30:04.211000+00:00"
},
"contacts_count": 412,
"subscribed_count": 398,
"created_at": "2026-10-02T09:14:03.551000+00:00",
"updated_at": "2026-10-02T09:14:03.551000+00:00"
}{
"error": "Segment not found"
}Update a segment
Updates the fields you pass and leaves the others unchanged. audience_ids and conditions are replaced as a whole. Requires an API key with the full scope.
Campaigns evaluate a segment when they send, so new rules apply to every campaign that hasn’t sent yet, including scheduled ones.
On a tracked segment, changing audience_ids or conditions compares the stored members with the new rules. Contacts who join or leave because of the change send segment.contact_added and segment.contact_removed events with reason set to segment_updated. Webhooks receive them, but they don’t start automations.
/segments/{id}Path parameters
idstringrequiredseg_…).Body parameters
namestringdescriptionstring | nullnull or an empty string clears it.audience_idsstring[][] means every contact in the workspace.conditionsobjecttrackedbooleanReturns
Returns the updated segment object with fresh counts.
| Status | When |
|---|---|
404 |
The segment doesn’t exist. |
422 |
A field or rule is invalid, or tracked differs from the segment’s current value. errors is keyed by field path. |
{
"object": "segment",
"id": "seg_2nYs9Kd1Lq3vB8wXcE4fT7uRm0p",
"name": "Pro customers renewing this month",
"description": "Pro and Enterprise plans that renew in the next 30 days.",
"audience_ids": ["aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a"],
"conditions": {
"match": "all",
"groups": [
{
"match": "all",
"rules": [
{ "field": "custom_fields.plan", "operator": "in", "value": ["pro", "enterprise"] },
{ "field": "custom_fields.renews_on", "operator": "in_next_days", "value": 30 }
]
}
]
},
"tracked": true,
"tracking": {
"status": "active",
"synced_at": "2026-10-18T00:30:04.211000+00:00"
},
"contacts_count": 412,
"subscribed_count": 398,
"created_at": "2026-10-02T09:14:03.551000+00:00",
"updated_at": "2026-10-18T12:00:00.000000+00:00"
}{
"error": "Segment not found"
}{
"message": "Validation failed. tracked: Tracking is chosen when a segment is created and can't be changed. Create a new segment instead.",
"errors": {
"tracked": [
"Tracking is chosen when a segment is created and can't be changed. Create a new segment instead."
]
}
}List segments
Returns the workspace’s segments, newest first, with how many of the plan’s segments are in use. Requires an API key with the full scope.
/segmentsQuery parameters
pageintegerdefault: 1limitintegerdefault: 10searchstringwith_countsbooleandefault: falsecontacts_count and subscribed_count to each segment. Counting evaluates every segment on the page, so it’s off by default.matchstringall (default) requires every filter. or matches any filter. See Filtering.
orderstringSort key for this list. See the sort keys below.
directionstringasc or desc.
Filter keys
Filters use key.condition=value query parameters, for example name.contains=customers or created_at.after=2026-09-01. See Filtering for the conditions per type.
| Key | Type | Notes |
|---|---|---|
name |
string | |
created_at |
date | |
updated_at |
date |
Sort keys for order: name, created_at, updated_at.
Returns
dataobject[]contacts_count and subscribed_count are only included with with_counts.total_recordsintegerusageobjectused (all segments, tracked or not), limit (segments the plan includes) and tracking_allowed (whether the plan includes tracked segments). See Limits.next_page_urlstring | nullnull on the last page. It carries only page and limit; add your search and filters again when you follow it.previous_page_urlstring | nullnull on the first page.{
"data": [
{
"object": "segment",
"id": "seg_2nYs9Kd1Lq3vB8wXcE4fT7uRm0p",
"name": "Pro customers renewing soon",
"description": "Pro and Enterprise plans that renew in the next 30 days.",
"audience_ids": ["aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a"],
"conditions": {
"match": "all",
"groups": [
{
"match": "all",
"rules": [
{ "field": "custom_fields.plan", "operator": "in", "value": ["pro", "enterprise"] },
{ "field": "custom_fields.renews_on", "operator": "in_next_days", "value": 30 }
]
}
]
},
"tracked": true,
"tracking": {
"status": "active",
"synced_at": "2026-10-18T00:30:04.211000+00:00"
},
"contacts_count": 412,
"subscribed_count": 398,
"created_at": "2026-10-02T09:14:03.551000+00:00",
"updated_at": "2026-10-02T09:14:03.551000+00:00"
}
],
"total_records": 1,
"usage": {
"used": 1,
"limit": 10,
"tracking_allowed": true
},
"next_page_url": null,
"previous_page_url": null
}Delete a segment
Deletes a segment. Requires an API key with the full scope.
- A segment that a campaign uses while it’s scheduled, queued, sending or testing can’t be deleted. Change the campaign’s recipients first.
- A segment can’t be deleted while any automation that isn’t deleted, in any status, uses it: in an Added to segment or Removed from segment trigger, in a goal, Wait until step or exit condition on those events, or in a Segment rule of a condition. Change those automations first.
- Draft campaigns that send to the segment lose it from their recipients, and
removed_from_campaignssays how many. Drafts that exclude the segment keep the exclusion, so they can’t be sent until you replace it: dropping it would send to the people you meant to leave out. Sent, canceled and archived campaigns keep the reference as history. - For a tracked segment, its stored members and growth history are deleted too.
/segments/{id}Path parameters
idstringrequiredseg_…).Returns
objectstringsegment.idstringnamestringdeletedbooleantrue.removed_from_campaignsinteger| Status | When |
|---|---|
404 |
The segment doesn’t exist. |
409 |
A scheduled, queued, sending or testing campaign uses the segment, or an automation starts from it. The message names them. |
{
"object": "segment",
"id": "seg_2nYs9Kd1Lq3vB8wXcE4fT7uRm0p",
"name": "Pro customers renewing soon",
"deleted": true,
"removed_from_campaigns": 1
}{
"error": "This segment is used by campaigns that are scheduled or sending: October launch. Change their recipients first.",
"message": "This segment is used by campaigns that are scheduled or sending: October launch. Change their recipients first."
}{
"error": "This segment is used by automations: Renewal reminder. Change their triggers, conditions or exit conditions first.",
"message": "This segment is used by automations: Renewal reminder. Change their triggers, conditions or exit conditions first."
}{
"error": "Segment not found"
}List segment contacts
Returns the contacts that match the segment at the moment you call it, newest first. Requires an API key with the full scope.
/segments/{id}/contactsPath parameters
idstringrequiredseg_…).Query parameters
pageintegerdefault: 1limitintegerdefault: 25searchstringmatchstringall (default) requires every filter. or matches any filter. See Filtering.
orderstringSort key for this list. See the sort keys below.
directionstringasc or desc.
Filter keys
The contacts of a segment accept the same filter and sort keys as List contacts, applied on top of the segment, for example email.ends_with=acme.com.
List filters are one layer of key.condition=value query parameters. See Filtering for match, order, direction and the condition list per type.
Filter keys
| Key | Type | Conditions | Notes |
|---|---|---|---|
email | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
first_name | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
last_name | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
name | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | Trimmed first name plus last name. |
audiences | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | Matches the alphabetically first audience name for the contact. |
created_at | date | exact, before, after, empty, not_empty | |
updated_at | date | exact, before, after, empty, not_empty | |
unsubscribed | boolean | exact, not_exact | |
audience_id | string | exact, not_exact | Only exact and not_exact. Value is an audience id (aud_...). |
custom_fields.* | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | Replace * with a custom field key, for example custom_fields.company.contains=Acme. |
Sort keys
Pass order as one of these keys and direction as asc or desc: email, first_name, last_name, name, audiences, created_at, updated_at, unsubscribed
Returns
dataobject[]object, id, email, first_name, last_name, custom_fields, unsubscribed, audiences (id, name, subscribed), created_at and updated_at. Contacts of a tracked segment also have joined_at.data[].joined_atstring | nullnull until tracking has recorded the contact, for example right after it started matching, while the segment is syncing, or while tracking is paused.total_recordsintegersubscribed_countintegernext_page_urlstring | nullnull on the last page. It carries page, limit and search; add your filters again when you follow it.previous_page_urlstring | nullnull on the first page.Returns 404 if the segment doesn’t exist.
{
"data": [
{
"object": "contact",
"id": "con_2nYs7Ab3Kd9Lm1Qw5Er8Ty2Ui4o",
"email": "ada@acme.com",
"first_name": "Ada",
"last_name": "Lovelace",
"custom_fields": {
"plan": "pro",
"renews_on": "2026-10-20"
},
"unsubscribed": false,
"audiences": [
{
"id": "aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a",
"name": "Customers",
"subscribed": true
}
],
"created_at": "2026-03-11T08:00:00.000000+00:00",
"updated_at": "2026-09-30T16:42:10.000000+00:00",
"joined_at": "2026-10-03T00:30:02.874000+00:00"
}
],
"total_records": 1,
"subscribed_count": 1,
"next_page_url": null,
"previous_page_url": null
}{
"error": "Segment not found"
}Retrieve segment growth
Returns the history of a tracked segment: one row per UTC day, oldest first, ending today. It’s the data behind the Growth chart on the segment page. Requires an API key with the full scope.
History starts when tracking starts. Contacts recorded by the first count after the segment was created, or after tracking resumed, count as members but not as joins.
/segments/{id}/growthPath parameters
idstringrequiredseg_…).Query parameters
daysintegerdefault: 30Returns
objectstringsegment_growth.segment_idstringdataobject[]data[].datestringYYYY-MM-DD.data[].members_countinteger | nullnull before tracking started.data[].joined_countintegerdata[].left_countinteger| Status | When |
|---|---|
404 |
The segment doesn’t exist. |
422 |
The segment isn’t tracked. |
{
"object": "segment_growth",
"segment_id": "seg_2nYs9Kd1Lq3vB8wXcE4fT7uRm0p",
"data": [
{ "date": "2026-10-12", "members_count": null, "joined_count": 0, "left_count": 0 },
{ "date": "2026-10-13", "members_count": 380, "joined_count": 0, "left_count": 0 },
{ "date": "2026-10-14", "members_count": 391, "joined_count": 14, "left_count": 3 },
{ "date": "2026-10-15", "members_count": 391, "joined_count": 0, "left_count": 0 },
{ "date": "2026-10-16", "members_count": 402, "joined_count": 12, "left_count": 1 },
{ "date": "2026-10-17", "members_count": 405, "joined_count": 6, "left_count": 3 },
{ "date": "2026-10-18", "members_count": 412, "joined_count": 9, "left_count": 2 }
]
}{
"error": "Growth is recorded for tracked segments only.",
"message": "Growth is recorded for tracked segments only."
}{
"error": "Segment not found"
}Preview a segment
Checks a segment definition without saving it: returns how many contacts match and a sample of them. The definition is validated like Create a segment, and a preview doesn’t count toward the plan’s segment limit. Requires an API key with the full scope.
/segments/previewBody parameters
audience_idsstring[]conditionsobjectlimitintegerdefault: 10Returns
objectstringsegment_preview.audience_idsstring[]conditionsobject{ match, rules } becomes one group and empty groups are dropped.contacts_countintegersubscribed_countintegercontactsobject[]Returns 422 with errors keyed by field path if the definition is invalid.
{
"object": "segment_preview",
"audience_ids": [],
"conditions": {
"match": "all",
"groups": [
{
"match": "all",
"rules": [
{ "field": "email_domain", "operator": "equals", "value": "acme.com" }
]
}
]
},
"contacts_count": 8,
"subscribed_count": 8,
"contacts": [
{
"object": "contact",
"id": "con_2nYs7Ab3Kd9Lm1Qw5Er8Ty2Ui4o",
"email": "ada@acme.com",
"first_name": "Ada",
"last_name": "Lovelace",
"custom_fields": {
"plan": "pro",
"renews_on": "2026-10-20"
},
"unsubscribed": false,
"audiences": [
{
"id": "aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a",
"name": "Customers",
"subscribed": true
}
],
"created_at": "2026-03-11T08:00:00.000000+00:00",
"updated_at": "2026-09-30T16:42:10.000000+00:00"
}
]
}{
"message": "Validation failed. conditions.groups.0.rules.0.operator: \"greater_than\" does not apply to Email domain.",
"errors": {
"conditions.groups.0.rules.0.operator": [
"\"greater_than\" does not apply to Email domain."
]
}
}List segment fields
Returns the fields that segment rules can use in this workspace: the contact fields, every custom field (typed by its custom field type), audience membership, purchase data and campaign engagement. Requires an API key with the full scope.
/segments/fieldsReturns
dataobject[]data[].keystringfield, for example email_domain or custom_fields.plan.data[].labelstringdata[].typestringstring, number, date, datetime, boolean, enum, multi, audience, metric, moment, purchase, view, cart, coupon or campaign_activity. See Create a segment. Activity fields such as purchased take an object value, see Activity rules.data[].groupstringcontact, custom_fields, audiences, commerce (purchase data) or engagement (campaign activity).data[].operatorsstring[]data[].valuesobject[]value and label: the options of select and multi-select custom fields, subscribed and unsubscribed for status, and the workspace’s audiences for audience. Absent for other fields.{
"data": [
{
"key": "email",
"label": "Email",
"type": "string",
"group": "contact",
"operators": ["equals", "not_equals", "contains", "not_contains", "starts_with", "ends_with", "in", "not_in", "is_set", "is_not_set"]
},
{
"key": "status",
"label": "Subscription status",
"type": "enum",
"group": "contact",
"operators": ["equals", "not_equals"],
"values": [
{ "value": "subscribed", "label": "Subscribed" },
{ "value": "unsubscribed", "label": "Unsubscribed" }
]
},
{
"key": "audience",
"label": "Audience",
"type": "audience",
"group": "audiences",
"operators": ["in", "not_in"],
"values": [
{ "value": "aud_2nYs8Qm4Hc1Zx7Vb3Ne6Tg9Lk2a", "label": "Customers" }
]
},
{
"key": "purchased",
"label": "Purchased",
"type": "purchase",
"group": "commerce",
"operators": [
"has",
"has_not"
]
},
{
"key": "custom_fields.renews_on",
"label": "Renews on",
"type": "date",
"group": "custom_fields",
"operators": ["on", "before", "after", "between", "in_last_days", "more_than_days_ago", "in_next_days", "is_set", "is_not_set"]
}
]
}