Skip to navigation

Advanced segments

An advanced segment’s membership is set by its definition. You send a definition when you create or update a segment with POST /3.0/segments or PATCH /3.0/segments/{segment_id}, and GET /3.0/segments/{segment_id} returns it. Working with advanced segments requires a Mailchimp plan that includes advanced segmentation.

A definition is a tree:

  • Groups combine their children with AND or OR.
  • Conditions each test one thing about a contact, such as an email address, a tag, a campaign they opened or a purchase they made.
  • The root of the tree is always a group. It may also say which contacts are in scope at all (the contacts object).
{
"contacts": { "email": { "marketing": [ { "sendable": true } ] } },
"match": "all",
"conditions": [
{ "field": "merge0", "op": "contains", "value": "@example.com" },
{
"match": "any",
"conditions": [
{ "field": "static_segment", "op": "static_is", "value": 8662415 },
{ "field": "rating", "op": "greater", "value": 3 }
]
}
]
}

This selects subscribed email contacts whose address contains @example.com and who either carry tag 8662415 or have a contact rating above 3.

Read-only segments

Every segment in a list or a read carries read_only:

"read_only": false"read_only": true
What it isAn advanced segment, built in Mailchimp or through this APIA segment another Mailchimp tool maintains, such as one built from Google Analytics data or by the AI segment builder
definition in a readYesNo
List, read, count, snapshot, page membersYesYes
Update (PATCH), delete (DELETE)YesNo: returns a 400

When you create a segment, definition is required, and its root group must have match and conditions. When you read one, definition is present only if read_only is false. read_only can’t be sent in a PATCH.

Creating an advanced segment, or updating or taking a snapshot of one, requires an account whose plan includes advanced segmentation. Without it, those requests return a 403. Snapshots of read-only segments don’t need it.

The rest of this page describes definitions, so it applies to segments that aren’t read-only.

Compatibility

Within an API version, existing fields keep their names, types and meaning, and aren’t removed. Mailchimp may add new fields, both to responses and to definitions, without a new version. Ignore fields you don’t recognize rather than rejecting the response.

Groups

KeyTypeRequiredDescription
match"all" or "any"Yesall: a contact must satisfy every child. any: a contact must satisfy at least one child. A node with match is a group.
conditionsarrayYesThe group’s children. In the root, each child is a condition or a group, in any mix and order. In a nested group, each child is a condition. Must be non-empty in a nested group; an empty root selects every contact in scope.
contactsobjectNoRoot group only. Which contacts are in scope. See Contacts in scope. Omit it to include every contact.
schema_versionintegerNoRoot group only. Format version; responses always return 2.

Groups nest up to 2 levels deep, counting the root: a root group can hold conditions and groups, and those groups hold only conditions. This is the deepest segment the segment builder can edit.

{
"match": "all",
"conditions": [
{ "field": "merge0", "op": "notcontain", "value": "@competitor.com" },
{ "field": "static_segment", "op": "static_not", "value": 1234 }
]
}

This selects contacts whose address doesn’t contain @competitor.com and who don’t carry tag 1234.

Conditions

A condition has a field naming what it tests, an op saying how, and usually a value. Which ops, values and filters a field accepts is listed per field in the condition reference.

KeyTypeRequiredDescription
fieldstringYesWhat the condition tests, for example merge0 (email address), static_segment (tag) or email_campaign_activity. A node with field is a condition.
opstringYesThe comparison, for example is, contains, greater, date_within. Required on every condition and every filter. Some fields accept any, meaning no constraint.
valuestring, number, boolean or arrayDepends on the field and opWhat to compare against.
filtersarray of conditionsDepends on the fieldNarrows the condition, for example to a specific campaign or a date range. Every filter must hold together with the condition. Filters are conditions, never groups.
value_op"and" or "or"Depends on the fieldHow a list in value combines, on fields that accept several values.
extrastring or arrayDepends on the fieldA second operand some fields need, for example the end of a date range.
locationobjectDepends on the field{region, city, country_code, lat, lng} for location conditions.
namespace, event_namestringCustom events onlyIdentify the event on a custom event condition.
typestringCustom event property filters onlyThe property’s type: string, integer, decimal, boolean or datetime.

Any other key is rejected with a 400.

{
"field": "email_campaign_activity",
"op": "open",
"filters": [
{ "field": "campaign", "op": "is", "value": 17795293 }
]
}

This selects contacts who opened campaign 17795293 (its web_id).

Contacts in scope

The root’s contacts object limits the segment to contacts in particular subscription states, per channel, before any condition applies. Omit it to include every contact on every channel: email, SMS and WhatsApp. When present it must name at least one entry.

{
"contacts": {
"email": {
"marketing": [ { "sendable": true } ],
"transactional": [ { "sendable": true } ]
},
"sms": { "marketing": [ { "sendable": true } ] }
},
"match": "all",
"conditions": []
}

Each channel holds lists of entries. A contact is in scope if it matches any entry on any channel.

Channel and listEntryContacts it covers
email.marketing{"sendable": true}Subscribed to email marketing.
email.marketing{"sendable": false, "consent": "denied"}Unsubscribed from email marketing. Includes contacts an account user unsubscribed, not only contacts who opted out themselves.
email.marketing{"sendable": false, "reason": "deliverability"}Cleaned: removed after bounces or other delivery problems.
email.marketing{"sendable": false}Every email contact who can’t receive marketing: unsubscribed, cleaned and transactional-only.
email.transactional{"sendable": true}Transactional-only: can receive transactional email but never subscribed to marketing.
sms.marketing{"sendable": true}Subscribed to SMS marketing.
sms.marketing{"sendable": false, "consent": "denied"}Opted out of SMS marketing.
sms.marketing{"sendable": false, "consent": "unknown"}Has an SMS number but never subscribed.
sms.marketing{"sendable": false}Every SMS contact who can’t receive marketing (both rows above).
whatsapp.marketing{"sendable": true}Subscribed to WhatsApp marketing.
whatsapp.marketing{"sendable": false, "consent": "denied"}Unsubscribed from WhatsApp marketing.
whatsapp.marketing{"sendable": false, "consent": "unknown"}Never subscribed to WhatsApp marketing.
whatsapp.marketing{"sendable": false}Every WhatsApp contact who can’t receive marketing (both rows above).

Also accepted:

  • "consent": "confirmed" may accompany any entry. It covers the same contacts as the entry without it.
  • email.marketing {"sendable": false, "consent": "unknown"} is the same population as email.transactional {"sendable": true}.
  • email.transactional {"sendable": false} is valid but covers no contacts.

Rejected with a 400:

  • "sendable": true with any consent other than "confirmed", or with any reason.
  • consent and reason in the same entry.
  • "consent": "consented".
  • reason on SMS or WhatsApp.
  • sms.transactional and whatsapp.transactional, which are reserved.

Ids in condition values

Some conditions name another Mailchimp object.

  • Campaigns: use the campaign’s web_id, the integer returned by GET /3.0/campaigns, not its id.

  • Tags and static segments (static_segment): use the tag’s or segment’s numeric id from GET /3.0/lists/{list_id}/segments.

  • Beta: interest groups, marketing permissions and e-commerce stores. These conditions take Mailchimp’s internal id, which other API endpoints don’t return. To find it:

    1. Build an advanced segment in Mailchimp that uses the interest, permission or store.
    2. Read that segment with GET /3.0/segments/{segment_id}.
    3. Copy the value from its definition.

    The format of these conditions may change.

Limits

LimitValueHow it’s counted
Conditions per definition100Every condition, including filters.
Group nesting depth2Levels of groups, counting the root as 1. Filters don’t add depth.

A definition over either limit is rejected with a 400 that names the limit. Limits apply when you write a definition. A segment built in Mailchimp that exceeds them still reads back normally, but writing that definition back returns a 400.

Errors

Errors use the standard Marketing API error format.

Plan without advanced segmentation. Creating an advanced segment, updating one, or taking a snapshot of one returns HTTP 403 when the account’s plan doesn’t include advanced segmentation:

{ "title": "Forbidden", "status": 403, "detail": "This account's plan doesn't include advanced segmentation." }

Invalid definitions return HTTP 400.

  • Structural problems put the reason in detail, for example an unknown key, a bad match, a misplaced contacts or an exceeded limit:

    { "title": "Bad Request", "status": 400, "detail": "'match' must be \"all\" or \"any\"" }
  • Condition problems set detail to segment conditions failed validation, with one errors[] entry per reason, for example an op a field doesn’t support or a value out of range:

    {
    "title": "Invalid Resource",
    "status": 400,
    "detail": "segment conditions failed validation",
    "errors": [ { "field": "definition", "message": "op must be one of is | not | contains | notcontain | starts | ends | greater | less | blank | blank_not" } ]
    }

Reading a definition back

GET /3.0/segments/{segment_id} returns the definition in the same format, with a few normalizations. Each one selects the same contacts you wrote:

  • contacts lists one entry per subscription state. Broad spellings come back as the states they cover. For example, email.marketing [{"sendable": false}] reads back as three entries: unsubscribed, cleaned and transactional-only. A segment created without contacts reads back with every state listed. Writing the response back unchanged stores the same scope.

  • A root that mixes conditions with groups reads back with its conditions wrapped in one group of the same match. The groups stay where they were, beside that wrapper. A root that holds only conditions, or only groups, reads back unchanged.

    { "match": "all", "conditions": [
    { "field": "merge0", "op": "starts", "value": "a" },
    { "field": "rating", "op": "greater", "value": 3 },
    { "match": "any", "conditions": [ { "field": "static_segment", "op": "static_is", "value": 1234 } ] }
    ] }

    reads back as

    { "match": "all", "conditions": [
    { "match": "all", "conditions": [
    { "field": "merge0", "op": "starts", "value": "a" },
    { "field": "rating", "op": "greater", "value": 3 }
    ] },
    { "match": "any", "conditions": [ { "field": "static_segment", "op": "static_is", "value": 1234 } ] }
    ] }
  • Empty extra values are omitted, and schema_version is always 2.

Condition reference

Fields are grouped by what they test. Each section lists the ops, the value format, the filters, and an example.

Availability, per field:

Contact data and audience membership

These conditions select contacts by what is stored on their profile: email address, merge fields, language, VIP status, rating, key dates, signup source, tags, groups, subscription status, marketing permissions, age gating and predicted location. None of them take filters. ipgeo is the only one that uses location.

There is no timezone condition. Date conditions are evaluated in a fixed timezone, which each section below names.

merge0 — Email address

Availability: Generally available Compares the contact’s email address with one or more strings.

OpMeaningValue
isEmail equals a valueString or array of strings
notEmail does not equal the value(s)String or array of strings
containsEmail contains the substringString or array of strings
notcontainEmail does not contain the substringString or array of strings
startsEmail starts with the valueString or array of strings
endsEmail ends with the value, for example a domainString or array of strings
greaterEmail sorts alphabetically after the valueString
lessEmail sorts alphabetically before the valueString
blankContact has no email addressOmit
blank_notContact has an email addressOmit

Example:

{ "field": "merge0", "op": "ends", "value": "@example.com" }
{ "field": "merge0", "op": "notcontain", "value": ["@gmail.com", "@yahoo.com"], "value_op": "and" }

Notes:

  • value is required for every op except blank and blank_not. Each entry is trimmed and must be at most 315 characters.
  • value_op defaults to "or", so the condition matches if any value matches. With not or notcontain, "or" means “differs from at least one value”, which matches almost everyone. Use "value_op": "and" to mean “matches none of these”.
  • If is or not is sent with an empty value ("", [] or [""]), it is saved as blank or blank_not.

merge<N> — Merge fields

Availability: Generally available Compares the contact’s value in one audience merge field. N is the field’s merge_id from GET /3.0/lists/{list_id}/merge-fields, an integer from 1 to 80 (for example merge3). The email address is merge0, documented above.

Mailchimp looks up the merge field’s type, and the type decides which ops and values are allowed. Don’t send a type yourself.

Merge field typeTreated asAllowed ops
text, address, zip, phone, website, image URL, dropdown, radio buttonstextis, not, contains, notcontain, starts, ends, greater, less, blank, blank_not, geoin
numbernumberis, not, greater, less, blank, blank_not
datedateis, not, greater, less, date_within, date_notwithin, blank, blank_not
birthdaybirthdayis, starts, ends, blank, blank_not
OpMeaningValue
isText: exact match. Number: equal. Date: on that day. Birthday: on that month and dayText, number or date: a value or array of values. Birthday: "MM/DD"
notText, number or date: not equal or not on that day. Includes contacts with no valueText or number: a value or array of values. Date: a date
contains / notcontainText contains, or does not contain, the substring. notcontain includes contacts with no valueString or array of strings
startsText: starts with. Birthday: month isText: a string or array of strings. Birthday: two-digit month, "01"–"12"
endsText: ends with. Birthday: day isText: a string or array of strings. Birthday: two-digit day, "01"–"31"
greater / lessText: alphabetically after or before. Number: strictly greater or less. Date: after the end of that day, or before the start of itA string, number or date
date_withinDate in the last N days, from 00:00 N days ago through the end of todayInteger number of days, for example "30"
date_notwithinDate outside that window. Includes contacts with no valueInteger number of days
blankText or birthday: empty or never set. Number or date: never setOmit
blank_notText or birthday: set and not empty. Number or date: setOmit
geoinThe ZIP code in this field is within value miles of the ZIP code in extraRadius in miles, greater than 0 and no more than 3000. extra is required

Example:

{ "field": "merge5", "op": "greater", "value": "100" }
{ "field": "merge4", "op": "geoin", "value": "25", "extra": "30303" }

Notes:

  • value is required for is, not, contains, notcontain, starts, ends, date_within and date_notwithin. Each entry must be at most 315 characters.
  • Number fields: every value must be numeric.
  • Date fields: send YYYY-MM-DD, or an ISO date-time with an offset (YYYY-MM-DDThh:mm:ssZ). Day boundaries are evaluated in UTC. is and not use only the first value.
  • Date date_within and date_notwithin take a whole number of days. Tokens like 7days or 1month are rejected, and decimals don’t behave as expected.
  • Birthday values must be zero-padded ("06", not "6"). Only the first value is used.
  • Dropdown and radio button values are the choice labels exactly as defined on the field.
  • geoin is for fields that hold US ZIP codes. extra must be a 5-digit US ZIP code.
  • value_op ("and" or "or", default "or") works as it does for merge0. Use "and" with not or notcontain to mean “matches none of these”.
  • An op that isn’t allowed for the field’s type is rejected, with a message listing the ops that are valid.

language — Language

Availability: Generally available The contact’s language preference.

OpMeaningValue
isLanguage equals the valueOne language code
notLanguage is not the valueOne language code
blankLanguage is unknownOmit
blank_notLanguage is knownOmit

Language codes (case-insensitive): en English, ar Arabic, af Afrikaans, be Belarusian, bg Bulgarian, ca Catalan, zh Chinese (Simplified), zh_CN Chinese (Traditional), hr Croatian, cs Czech, da Danish, nl Dutch, et Estonian, fa Farsi, fi Finnish, fr French (France), fr_CA French (Canada), de German, el Greek, he Hebrew, hi Hindi, hu Hungarian, is Icelandic, id Indonesian, ga Irish, it Italian, ja Japanese, km Khmer, ko Korean, lv Latvian, lt Lithuanian, mt Maltese, ms Malay, mk Macedonian, no Norwegian, pl Polish, pt Portuguese (Brazil), pt_PT Portuguese (Portugal), ro Romanian, ru Russian, sr Serbian, sk Slovak, sl Slovenian, es Spanish (Mexico), es_ES Spanish (Spain), sw Swahili, sv Swedish, ta Tamil, th Thai, tr Turkish, uk Ukrainian, vi Vietnamese, xxxxx Custom.

Example:

{ "field": "language", "op": "is", "value": "fr_CA" }

Notes:

  • value is a single string and is required for is and not. Arrays are rejected. To match several languages, use a group with "match": "any".

gmonkey — VIP status

Availability: Generally available Whether the contact is marked as a VIP.

OpMeaningValue
memberContact is a VIPOmit
notmemberContact is not a VIPOmit

Example:

{ "field": "gmonkey", "op": "member" }

rating — Contact rating

Availability: Generally available The contact’s star rating, from 1 to 5.

OpMeaningValue
isRating equals the valueInteger 1–5
notRating is not the value. Includes contacts without a ratingInteger 1–5
greaterRating is greater than the valueInteger 1–5
lessRating is less than the valueInteger 1–5

Example:

{ "field": "rating", "op": "greater", "value": 3 }

Notes:

  • value is required and must be a single integer from 1 to 5, sent as a number or a numeric string.

timestamp_opt, info_changed — Subscription date and Info changed

Availability: Generally available

FieldSelects by
timestamp_optEmail subscription date: when the contact’s email subscription record was created
info_changedInfo changed: when the contact’s profile information last changed

Both fields take the same ops and values. Dates are evaluated in the account’s timezone.

OpMeaningValue
isOn that dayDate YYYY-MM-DD
notNot on that dayDate
greaterAfter that day, meaning the next day or laterDate
lessBefore that dayDate
betweenFrom the start of the first day through the end of the second, inclusiveArray of exactly 2 dates
date_withinFrom 00:00 N days ago through the end of todayPositive integer number of days
date_notwithinOutside that windowPositive integer number of days
campaign_isOn the day the campaign was sentCampaign web_id, or "last"
campaign_greaterAfter the day the campaign was sentCampaign web_id, or "last"
campaign_lessBefore the day the campaign was sentCampaign web_id, or "last"

Example:

{ "field": "timestamp_opt", "op": "between", "value": ["2026-01-01", "2026-03-31"] }
{ "field": "info_changed", "op": "campaign_greater", "value": "last" }

Notes:

  • value is required for every op.
  • Use plain YYYY-MM-DD dates. A date-time is accepted, but its offset is ignored. is, not, greater and less use only the first value.
  • date_within and date_notwithin take one whole number of days. Tokens like 7days are rejected.
  • campaign_* ops take the web_id (an integer) of a sent campaign from GET /3.0/campaigns, or "last" for the audience’s most recently sent campaign. Check that the campaign exists and has been sent: a bad campaign value may not be rejected when you save, but the segment will fail when it is counted or used.

metadata_created — Contact created date

Availability: Generally available When the contact record was created in the audience, across all channels.

OpMeaningValue
isOn that dayDate YYYY-MM-DD
notNot on that dayDate
greaterAfter that dayDate
lessBefore that dayDate
betweenFrom the start of the first day through the end of the second, inclusiveArray of exactly 2 dates
date_withinFrom 00:00 N days ago through the end of todayPositive integer number of days
date_notwithinOutside that windowPositive integer number of days
campaign_isOn the day the campaign was sentCampaign web_id, or "last"
campaign_greaterAfter the day the campaign was sentCampaign web_id, or "last"
campaign_lessBefore the day the campaign was sentCampaign web_id, or "last"

Example:

{ "field": "metadata_created", "op": "date_within", "value": "7" }

Notes:

  • value is required for every op. Dates are YYYY-MM-DD or an ISO date-time with an offset.
  • Always send two dates for between. A single value is read as “within N days”.
  • date_within and date_notwithin take a whole number of days. 1month and similar tokens fail.
  • campaign_* values work as they do for timestamp_opt.

original_signup_source, source — Signup source

Availability: Generally available How the contact originally joined the audience. value is the source type. The optional extra narrows the match to one specific source of that type, such as a particular import.

FieldNotes
original_signup_sourceSignup source. Use this field.
sourceSignup activity. Accepted and treated the same as original_signup_source.
OpMeaningValue
source_isContact joined through this sourceSource type id
source_notContact did not join through this sourceSource type id

Source type ids:

IdSourceIdSource
1Pre-existing13Inbox
2Unknown14Contact Form
3Admin Add50–53E-commerce (generic, PayPal, DPD, E-Junkie)
4Import500Mailchimp for Square
5Hosted Signup Form600ShopSync
6Facebook Signup Form700QuickBooks
7Embed Form1000API (generic)
8Twitter1001–1005, 1008API plugins and SDKs
9Popup Form1006Website
10Landing Page1009–1014Mailchimp mobile app imports and scans
11Survey1015CRM
12Website Popup Form1019QuickBooks Online

Connected apps can also appear as sources, identified by large integer ids.

Example:

{ "field": "original_signup_source", "op": "source_is", "value": "7" }
{ "field": "original_signup_source", "op": "source_not", "value": "4", "extra": "987654" }

Notes:

  • value is required. Send it as a numeric string, for example "10".
  • extra is optional. Omit it, or send "any", to match any source of that type. Otherwise send the id of one specific source, for example an import id for type 4 or a landing page id for type 10. Beta: the specific-source id takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the source, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change. With extra, source_is means “this exact source” and source_not means “not this exact source”.

static_segment — Tags

Availability: Generally available Whether the contact has particular tags. Values are tag ids: the integer id of a tag from GET /3.0/lists/{list_id}/tag-search or of a static segment from GET /3.0/lists/{list_id}/segments.

OpMeaningValue
static_isContact has the tagOne tag id
static_notContact does not have the tag. Includes contacts with no tagsOne tag id
isContact has at least one of the tagsArray of 1–20 tag ids
is_everyContact has every tag listedArray of 1–20 tag ids
notContact has none of the tags. Includes contacts with no tagsArray of 1–20 tag ids
not_everyContact is missing at least one of the tagsArray of 1–20 tag ids

Example:

{ "field": "static_segment", "op": "static_is", "value": 8662415 }
{ "field": "static_segment", "op": "is_every", "value": [8662415, 8661935] }

Notes:

  • value is required. Ids are integers, sent as numbers or numeric strings.
  • static_is and static_not take exactly one id. An array is rejected; use is, is_every, not or not_every for several tags.

interests-<N> — Groups

Availability: Beta. Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the group, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change. Whether the contact belongs to particular groups (interests). N is the internal id of the group category, and the values are the internal ids of the groups in it. Copy both from a segment built in Mailchimp.

OpMeaningValue
interestcontainsContact is in at least one of the groupsArray of group ids, or one id
interestcontainsallContact is in every group listedArray of group ids, or one id
interestnotcontainsContact is in none of the groups. Includes contacts in no groupsArray of group ids, or one id

Example:

{ "field": "interests-1234", "op": "interestcontains", "value": ["44401", "44405"] }

Notes:

  • value is required and must not be empty.
  • Matching uses only the group ids in value. Keep the field and the values from the same category, as Mailchimp writes them.

list_email_status — Email subscription status

Availability: Generally available The contact’s email subscription status.

OpMeaningValue
isStatus is one of the valuesStatus code or array of codes
notStatus is none of the valuesStatus code or array of codes
CodeStatus
YSubscribed
NUnsubscribed
TTransactional (non-subscribed)
BCleaned

Example:

{ "field": "list_email_status", "op": "is", "value": ["Y", "T"] }

Notes:

  • value is required. Codes are case-insensitive. Other values, such as "subscribed", are rejected.
  • This condition is combined with the segment’s top-level contact scope. It can narrow that scope, but it can’t add back contacts the scope excludes.

marketing_preference — Marketing permissions

Availability: Beta. Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the marketing permission, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change. Whether the contact has granted a marketing permission (GDPR). Relevant only to audiences with GDPR fields enabled.

OpMeaningValue
isContact has granted the permissionOne permission id
notContact has not granted it. Includes contacts with no permissionsOne permission id

Example:

{ "field": "marketing_preference", "op": "is", "value": "301" }

Notes:

  • value is required and must be a single numeric id, not the permission’s label.

age_gating — Age gating

Availability: Generally available The contact’s SMS age-verification outcome. Relevant only to audiences with SMS marketing.

OpMeaningValue
isOutcome is one of the valuesArray of strings from "true", "false", "unknown"
notOutcome is none of the valuesArray of strings from "true", "false", "unknown"
anyContact has an age-verification recordOmit
not_anyContact has no age-verification recordOmit

Values: "true" means verified, "false" means excluded, and "unknown" means no record.

Example:

{ "field": "age_gating", "op": "is", "value": ["true"] }
{ "field": "age_gating", "op": "not_any" }

Notes:

  • value is required for is and not. Always send an array of strings, not JSON booleans. A bare "unknown" string, not in an array, matches no one.
  • "unknown" may be combined with "true" or "false": {"op": "is", "value": ["true", "unknown"]} matches contacts who are verified or have no record, and not with the same values matches everyone else.

ipgeo — Predicted location

Availability: Generally available The contact’s predicted location, estimated from data such as IP address. This is the only condition in this family that uses location.

OpMeaningValueAlso needs
ipgeoinWithin value miles of a pointRadius in mileslocation.lat, location.lng
ipgeonotinNot within value miles of a pointRadius in mileslocation.lat, location.lng
ipgeoinzipWithin value miles of a US ZIP codeRadius in mileslocation.lat, location.lng of the ZIP code
ipgeocountryIn the countryTwo-letter country code—
ipgeonotcountryKnown country, other than this oneTwo-letter country code—
ipgeostateIn the US stateTwo-letter US state code, for example "GA"—
ipgeonotstateIn the US, in a known state other than this oneTwo-letter US state code—
ipgeocityIn the cityOmitlocation.city
ipgeonotcityKnown city, other than this oneOmitlocation.city
ipgeoiszipIn the US ZIP codeZIP code string—
ipgeonotzipIn the US, in a known ZIP code other than this oneZIP code string—
ipgeounknownNo predicted locationOmit—

Example:

{ "field": "ipgeo", "op": "ipgeoin", "value": "50",
"location": { "city": "Atlanta", "region": "GA", "country_code": "US", "lat": 33.749, "lng": -84.388 } }
{ "field": "ipgeo", "op": "ipgeocountry", "value": "CA" }

Notes:

  • The radius is a number of miles. The Mailchimp app offers 25, 50, 75, 100, 150 and 200, but any positive number works.
  • ipgeoinzip doesn’t look up the ZIP code. Send the ZIP code’s latitude and longitude in location.lat and location.lng.
  • ipgeocity and ipgeonotcity match the city name in location.city only. They are not limited by region or country.
  • location.region and location.country_code are stored with the segment, but they don’t affect matching.
  • The negative ops ipgeonotcountry, ipgeonotstate, ipgeonotcity and ipgeonotzip exclude contacts whose location is unknown. To include them, add an ipgeounknown condition in a group with "match": "any".

Email, SMS and WhatsApp engagement and status

These conditions select contacts by what they did with your email, SMS and WhatsApp messages (sends, opens, clicks, replies, bounces, keywords) and by their subscription status, subscription date and phone country on each channel.

Shared filters used by the activity conditions (email_campaign_activity, sms_campaign_activity, whatsapp_campaign_interaction) are described once, in Shared activity filters, at the end of this section.

email_campaign_activity — Email campaign interaction

Availability: Generally available

Selects contacts who did, or did not, receive, open, click, reply to, or bounce from your email campaigns. Filters narrow the match by campaign, time, link, click type, open type and number of events.

With a positive op (sent, open, click, reply, bounce), a contact matches when one activity record satisfies all the filters together. With a no_* op, a contact matches when no activity record satisfies all the filters together. That includes contacts with no activity at all.

OpMeaningValue
sent / no_sentWas / was not sent the campaignOmit
open / no_openOpened / did not openOmit
click / no_clickClicked / did not clickOmit
reply / no_replyReplied / did not replyOmit
bounceThe send bounced (soft or hard bounce)Omit

Filters (filters is required and must contain at least one filter):

Filter fieldOpsValueNotes
campaignany, is, not, anylast5, anylast10, anylast20, anylast50, alllast5, alllast10, alllast20, alllast50For is / not: one campaign web_id (integer). Omit for the others.Allowed with every op. See below.
timeframeSee timeframeAllowed with every op.
click_urlany, is, not, contains, notcontain, starts, endsA URL or text fragment (string)click / no_click only. See below.
click_typeiscontact_clicks, bot_clicks, or all_clicksclick / no_click only. See click_type.
open_typeany, is, notapple_mppopen only. See below.
number_eventsSee number_eventssent, open, click only.

campaign filter

OpMeaning
anyAny campaign. Send this when you don’t want to narrow by campaign.
isActivity on this campaign. If the campaign is an A/B test, its test variants are included.
notActivity on some campaign other than this one. With a positive op this is not the same as “didn’t”: for “didn’t open campaign X”, use no_open with campaign is X.
anylast5 … anylast50Positive op: activity on any of the list’s N most recently sent campaigns. no_* op: missed at least one of them.
alllast5 … alllast50Positive op: activity on every one of the list’s N most recently sent campaigns. no_* op: activity on none of them.

click_url filter

OpMeaning
anyAny link.
is / notThe clicked URL starts with / does not start with the value. Clicked URLs can include tracking parameters, so is matches by prefix.
contains / notcontainThe clicked URL contains / does not contain the value.
starts / endsThe clicked URL starts / ends with the value.

open_type filter (Apple Mail Privacy Protection)

OpMeaning
anyAny open.
is apple_mppThe contact’s opens of the campaign are only machine opens by Apple Mail Privacy Protection, with no human open.
not apple_mppThe contact has at least one human (non-MPP) open of the campaign.

Example:

Opened campaign 17795293 in the last month:

{ "field": "email_campaign_activity", "op": "open",
"filters": [
{ "field": "campaign", "op": "is", "value": 17795293 },
{ "field": "timeframe", "op": "date_within", "value": "1month" }
] }

Human clicks on a link containing “/sale” in any of the last 10 campaigns, more than twice:

{ "field": "email_campaign_activity", "op": "click",
"filters": [
{ "field": "campaign", "op": "anylast10" },
{ "field": "click_url", "op": "contains", "value": "/sale" },
{ "field": "click_type", "op": "is", "value": "contact_clicks" },
{ "field": "number_events", "op": "greater", "value": 2 }
] }

Notes:

  • Campaign ids are the campaign’s web_id from GET /3.0/campaigns (an integer), not its id. A non-numeric value is rejected.
  • Send one web_id per campaign filter. To match several specific campaigns, use a group with "match": "any".
  • “Most recently sent” campaigns for anylastN / alllastN are the list’s sent, non-deleted campaigns that delivered at least one email, newest send time first. A/B test variants are expanded automatically.
  • Op spellings are no_sent, no_open, no_click, no_reply. The SMS spellings (nosent, nodelivered) are rejected here.
  • value, value_op and extra are not used on this condition.
  • click_url: every op except any needs a non-empty string. greater and less are rejected.
  • open_type is or not requires a campaign filter. If you combine open_type is with campaign any, the campaign filter is treated as anylast50. With an “all” campaign op (alllastN) every campaign must satisfy the open type; with any other campaign op, at least one must.
  • open_type is / not cannot be combined with number_events is, greater or less (at_least_once is allowed).
  • A filter that belongs to another channel (for example sms_campaign) is not valid here.

email_marketing_engagement — Email engagement

Availability: Generally available

Selects contacts by how often they engage with your email, based on Mailchimp’s email activity score, or by being newly opted in.

OpMeaningValue
isEngagement level is this valueOne string: new, low, medium, high
notEngagement level is not this value (includes contacts with no score or no email opt-in date)Same
ValueLabel in MailchimpRule
newNew: not enough history to score yetOpted in to email within the last 30 days
lowRarelyLowest activity score, opted in more than 30 days ago
mediumSometimesMiddle activity score, opted in more than 30 days ago
highOftenHighest activity score, opted in more than 30 days ago

Example:

{ "field": "email_marketing_engagement", "op": "is", "value": "high" }

Notes:

  • value is a single lowercase string; "HIGH" is rejected. An array is rejected; to match several levels use a group with "match": "any".
  • filters, value_op and extra are not used.

sms_campaign_activity — SMS interaction

Availability: Requires SMS marketing on the audience

Selects contacts who were, or were not, sent or delivered SMS messages from your SMS campaigns or Customer Journeys, who clicked an SMS tracking link, or who texted a keyword.

With a positive op, a contact matches when one message or click satisfies all the filters together. With a negated op (nosent, nodelivered, no_click), a contact matches when no record satisfies all the filters together, including contacts with no SMS activity.

OpMeaningValue
sent / nosentWas / was not sent a message (sent, delivered or failed)Omit
delivered / nodeliveredWas / was not delivered a messageOmit
click / no_clickClicked / did not click a tracking linkOmit
used_keywordTexted this keywordThe keyword (string, required)

Filters (filters is required and must contain at least one filter):

Filter fieldOpsValueNotes
sms_campaignany, is, notFor is / not: one SMS campaign id (UUID string) or an array of them. Omit for any.Beta for is / not: see note below.
timeframeSee timeframeWith sent / delivered it applies to the message’s last status update; with click to the click time. Don’t combine with used_keyword.
sms_click_typeiscontact_clicks, bot_clicks, or all_clicksclick / no_click only. See click type filters.
number_eventsSee number_eventssent and click only.

Example:

Human clicks in one SMS campaign in the last 30 days:

{ "field": "sms_campaign_activity", "op": "click",
"filters": [
{ "field": "sms_campaign", "op": "is", "value": "5e143a22-0aaf-41b1-b0b9-dac4ffa74a68" },
{ "field": "timeframe", "op": "date_within_days", "value": 30 },
{ "field": "sms_click_type", "op": "is", "value": "contact_clicks" }
] }

Texted the keyword “JOIN”:

{ "field": "sms_campaign_activity", "op": "used_keyword", "value": "JOIN",
"filters": [ { "field": "sms_campaign", "op": "any" } ] }

Notes:

  • Beta (sms_campaign ids): Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the SMS campaign, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change.
  • Op spellings: nosent and nodelivered have no underscore; no_click has one. The email spelling no_sent is rejected.
  • There are no open, reply or bounce ops for SMS. For bounces, use sms_bounce_reason.
  • value is used only by used_keyword (a single string). value_op and extra are not used.
  • Use only the filters listed above. The email filters campaign, click_url and click_type are not valid here.
  • On some accounts sent, delivered and click also count WhatsApp messages. To target WhatsApp specifically, use whatsapp_campaign_interaction.

sms_bounce_reason — SMS bounce reason

Availability: Requires SMS marketing on the audience

Selects contacts with at least one SMS campaign or Customer Journey message that bounced, optionally with a specific error code. The error code, campaign and time filters all apply to the same message.

OpMeaningValue
anyA message bounced for any reasonOmit
isA message bounced with one of these error codesCode string or array of code strings (required)
CodeMeaning
4000Unknown error
4100Rejected by operator
4101MMS too large
4102Unexpected data value
4103Duplicate message
4104Message text too long
4105Carrier rate limit exceeded
4202Invalid source address
4203Mobile network congestion
4204Operator network or routing error
4205Operator provisioning issue
4301Suspended number
4302Handset or equipment error
5200Unrecognized carrier
5300Number not provisioned or blocked
5301Deactivated number
5302Number blocklisted

Filters (optional):

Filter fieldOpsValueNotes
sms_campaignany, is, notSMS campaign id (UUID string) or arrayBeta for is / not, same as under sms_campaign_activity.
timeframeany, is, not, greater, less, between, date_within, date_notwithin, campaign_is, campaign_greater, campaign_lessDates YYYY-MM-DD; date_within / date_notwithin take a number of days; campaign_* take a campaign web_id or "last"Applies to the message’s last status update.

Example:

Deactivated or blocklisted number, in the last 30 days:

{ "field": "sms_bounce_reason", "op": "is", "value": ["5301", "5302"],
"filters": [ { "field": "timeframe", "op": "date_within", "value": 30 } ] }

Notes:

  • Codes are not checked against the list above; an unknown code is accepted and matches nobody.
  • Every timeframe op except any needs a value. between takes [start, end], inclusive.
  • campaign_is / campaign_greater / campaign_less compare with the send date of an email campaign on the same audience (web_id), or of the audience’s most recently sent email campaign ("last").
  • Only sms_campaign and timeframe filters are accepted. Any other filter is rejected with Unsupported operation: <field>.

sms_contact_status — SMS subscription status

Availability: Requires SMS marketing on the audience

Selects contacts by their SMS marketing subscription status.

OpMeaningValue
status_isStatus is one ofString or array of codes
notStatus is not one ofSame
CodeStatus
YSubscribed
NUnsubscribed
NONNon-subscribed

Example:

{ "field": "sms_contact_status", "op": "not", "value": ["N", "NON"] }

Notes:

  • The op is status_is, not is.
  • Codes are case-insensitive. P (pending) and any other code are rejected. An empty array is rejected.
  • filters, value_op and extra are not used.

sms_timestamp_opt — SMS subscription date

Availability: Requires SMS marketing on the audience

Selects contacts by the date their SMS channel was added.

OpMeaningValue
isOn that dayOne date
greaterAfter that dayOne date
lessBefore that dayOne date
betweenWithin the range, inclusive by whole days[start, end]
date_withinIn the last N daysOne integer (days)
campaign_isOn the send date of a campaignCampaign web_id or "last"
campaign_greaterAfter the send date of a campaignSame
campaign_lessBefore the send date of a campaignSame

Example:

{ "field": "sms_timestamp_opt", "op": "between", "value": ["2025-02-01", "2025-02-28"] }
{ "field": "sms_timestamp_opt", "op": "date_within", "value": 30 }

Notes:

  • Dates are YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS±HH:MM.
  • date_within takes a number of days. "1month" and similar strings are rejected.
  • "last" means the audience’s most recently sent email campaign. A campaign without a send date is rejected.
  • To select dates outside a range, use a group with "match": "any" that holds a less condition on the first day and a greater condition on the last day. Contacts without an SMS subscription date match neither.
  • filters, value_op and extra are not used.

sms_country_code — Mobile phone country

Availability: Requires SMS marketing on the audience

Selects contacts by the country of their SMS phone number. On some accounts it also matches the country of the contact’s WhatsApp number: then in matches if either number is in one of the countries, and not_in matches only if neither number is.

OpMeaningValue
inCountry is one ofArray of ISO 3166-1 alpha-2 codes (required, non-empty)
not_inCountry is not one ofSame

Example:

{ "field": "sms_country_code", "op": "in", "value": ["US", "CA"] }

Notes:

  • Send country codes in uppercase.
  • Codes are not checked against the countries Mailchimp SMS supports; an unsupported country matches nobody.
  • The ops are in / not_in, not is / not.
  • filters, value_op and extra are not used.

whatsapp_campaign_interaction — WhatsApp interaction

Availability: Requires WhatsApp marketing on the audience

Selects contacts who were, or were not, sent, read, or clicked WhatsApp messages from your campaigns or Customer Journeys. Filters combine the same way as for sms_campaign_activity.

OpMeaningValue
sent / nosentWas / was not sent a message (sent, delivered or failed)Omit
opened / not_openedRead / did not read a messageOmit
click / no_clickClicked / did not click a tracking linkOmit

Filters (filters is required and must contain at least one filter):

Filter fieldOpsValueNotes
whatsapp_campaignany, is, notFor is / not: WhatsApp campaign id (UUID string) or array. Omit for any.Beta for is / not: see note below.
timeframeSee timeframeApplies to the last status update (sent), the read time (opened), or the click time (click).
whatsapp_click_typeiscontact_clicks, bot_clicks, or all_clicks (required)click / no_click only. See click type filters.
click_urlany, is, not, contains, notcontain, starts, endsA URL or text fragmentclick / no_click only. Same meanings as for email.
number_eventsSee number_eventssent and click only.

Example:

{ "field": "whatsapp_campaign_interaction", "op": "opened",
"filters": [
{ "field": "whatsapp_campaign", "op": "is", "value": "8c1f2b9e-3d4a-4b5c-9e6f-1a2b3c4d5e6f" },
{ "field": "timeframe", "op": "date_within_days", "value": 14 }
] }

Notes:

  • Beta (whatsapp_campaign ids): Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the WhatsApp campaign, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change.
  • Op spellings: nosent and not_opened (not no_sent / no_open).
  • There are no delivered or keyword ops for WhatsApp.
  • value, value_op and extra are not used.

whatsapp_contact_status — WhatsApp subscription status

Availability: Requires WhatsApp marketing on the audience

Selects contacts by their WhatsApp marketing subscription status.

OpMeaningValue
isStatus is one ofString or array: SUBSCRIBED, UNSUBSCRIBED
notStatus is not one ofSame

Example:

{ "field": "whatsapp_contact_status", "op": "is", "value": ["SUBSCRIBED"] }

Notes:

  • Values differ from SMS: use SUBSCRIBED / UNSUBSCRIBED, not Y / N, and the op is is, not status_is. Other values are accepted but match nobody.
  • Send values in uppercase.
  • not also matches contacts with no WhatsApp channel.
  • filters, value_op and extra are not used.

whatsapp_timestamp_opt — WhatsApp subscription date

Availability: Requires WhatsApp marketing on the audience

Selects contacts by the date their WhatsApp channel was added.

OpMeaningValue
anyNo date restrictionOmit
is / notOn / not on that dayOne date
greaterAfter that dayOne date
lessBefore that dayOne date
betweenWithin the range, inclusive[start, end]
date_withinIn the last N daysOne integer (days)
date_notwithinNot in the last N daysOne integer (days)

Example:

{ "field": "whatsapp_timestamp_opt", "op": "less", "value": "2025-06-01" }

Notes:

  • Dates are YYYY-MM-DD. Every op except any needs a non-empty value.
  • filters, value_op and extra are not used.

Shared activity filters

timeframe

Used by email_campaign_activity, sms_campaign_activity and whatsapp_campaign_interaction. (sms_bounce_reason has its own timeframe op list, above.)

OpMeaningValue
anyNo time restrictionOmit
date_withinFrom the start of the day N days/months ago through the end of today"7days", "1month", "3months", or an integer number of days
date_notwithinOutside that windowSame as date_within
date_within_daysIn the last N daysInteger 1–365
date_within_monthsIn the last N monthsInteger 1–12
betweenFrom the start of start through the end of end, inclusive[start, end]
greaterAfter the end of that dayOne date
lessBefore the start of that dayOne date
isWithin that calendar dayOne date
notNot within that calendar dayOne date

Dates are YYYY-MM-DD, optionally followed by THH:MM[:SS] and a Z or ±HH:MM offset.

number_events

Used by email_campaign_activity (with sent, open, click), sms_campaign_activity (with sent, click) and whatsapp_campaign_interaction (with sent, click). Counts the distinct activity records that match the condition’s other filters.

OpMeaningValue
at_least_onceAt least one (same as omitting the filter)Omit
isExactly NInteger 1–10
greaterMore than NInteger 1–10
lessFewer than NInteger 1–10

At most one number_events filter per condition.

Click type filters

click_type (email), sms_click_type (SMS) and whatsapp_click_type (WhatsApp) take op is and one value:

ValueMeaning
contact_clicksHuman clicks only
bot_clicksClicks identified as bots only
all_clicksAll clicks, including older clicks recorded before bot detection

Values must be lowercase as listed. With no_click, all_clicks means “has not clicked at all”. An empty value is treated as contact_clicks for click_type and sms_click_type; whatsapp_click_type requires a value.

E-commerce conditions

E-commerce conditions select contacts by what they did in a connected store: orders and what was in them, lifetime spend and order counts, storefront activity (page views, searches, product and collection views, carts, checkouts), reviews, back-in-stock requests, and predicted churn risk. Unless a section says otherwise, they need a connected e-commerce store. On an audience with no store data, a condition still saves; positive ops match nobody and negative ops match everybody.

Shared values and filters

These rules apply to every condition in this section.

Identifier formats

ConceptWhat to send
ProductThe product title, as text (the title of the product in the e-commerce API).
Product variantThe variant title, as text.
Category (ecomm_category)The product vendor, as text (the product’s vendor in the e-commerce API). Despite the name, it doesn’t match category names.
Collection (ecomm_collection)With is / not: the collection’s id in your store platform (for example a Shopify collection GID such as gid://shopify/Collection/123456789). With contains, notcontain, starts, ends: the collection name.
Discount codeThe promo code string.
CampaignThe campaign’s web_id from GET /3.0/campaigns (an integer), not its id.
Store (ecomm_store, ecomm_back_in_stock_request_store)Beta. Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the store, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change. It is not the store_id you use with /3.0/ecommerce/stores. Send it as a string.

Text ops. Filters on products, variants, categories, collections, page URLs and search text use the same ops:

OpMeaningValue
isExactly matches one of the valuesstring or array of strings
notMatches none of the valuesstring or array of strings
containsContains the textstring
notcontainDoesn’t contain the textstring
startsStarts with the textstring
endsEnds with the textstring

Money. Send amounts as a decimal JSON number or numeric string (100, "49.99"), with no currency symbol or thousands separator. Amounts must be zero or greater.

any filters. Every filter accepts "op": "any" with no value, meaning “no restriction”. Leaving the filter out does the same thing and is preferred.

How filters combine. On an activity condition (purchased, viewed, added to cart, and so on), the positive op matches contacts with at least one order or event that meets all the filters at once. The negative op (no_purchased, no_viewed, not_submitted, requested_not, …) matches contacts with no such order or event, including contacts who have no orders or events at all.

ecomm_timeframe filter

Restricts an order or event by when it happened. Dates are evaluated in the account’s timezone. Leave extra out; it is ignored.

OpMeaningValue
anyNo time restrictionomit
date_withinIn the last N days, from the start of the day N days ago through the end of todaywhole number of days as a string, e.g. "30"
date_notwithinNot in the last N dayssame as date_within
betweenOn or between two dates (inclusive)array of exactly 2 dates, ["2026-01-01", "2026-03-31"]
greaterAfter the given daydate
lessBefore the given daydate
isOn the given daydate
notNot on the given daydate
campaign_greaterAfter the day the campaign was sent"last" (the audience’s most recently sent campaign) or a campaign web_id
campaign_lessBefore the day the campaign was sentsame
campaign_isOn the day the campaign was sentsame
  • Dates are YYYY-MM-DD (a time and offset, YYYY-MM-DDTHH:MM:SS+00:00, is also accepted).
  • On ecomm, total_spent, spent_avg and orders_count, date_within / date_notwithin also accept "7days", "1month" and "3months" (calendar months).
  • date_within_days, date_within_months, blank and blank_not are not supported here.
  • A campaign_* value that doesn’t match a sent campaign in the audience is rejected with HTTP 400.

number_events filter

Counts how many matching orders the contact has. Allowed only under ecomm with purchased; the store event conditions below don’t accept it. At most one per condition.

OpMeaningValue
at_least_onceOne or more (the same as leaving the filter out)omit
isExactly Ninteger 1–10
greaterMore than Ninteger 1–10
lessFewer than Ninteger 1–10

ecomm — Purchase activity

Availability: Requires a connected e-commerce store. Contacts who have, or have not, placed an order that meets every filter. With no filters, purchased means “has placed any order”.

OpMeaningValue
purchasedAt least one order meets all filtersomit
no_purchasedNo order meets all filters (includes contacts with no orders)omit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or daysWhen the order was processed.
ecomm_campaignany, is, notcampaign web_id (integer) or array of themThe campaign the order is attributed to.
ecomm_storeany, is, notBeta store id (string) or arraySee identifier formats.
ecomm_productany + text opsproduct title(s)
ecomm_product_variantany + text opsvariant title(s)
ecomm_categoryany + text opsvendor name(s)Matches the product vendor.
ecomm_collectionany + text opscollection id(s) for is/not; name for the others
ecomm_order_totalany, is, not, greater, lessone money amountThe order total.
ecomm_discount_codeany, is, not, used, not_used, containscode string(s); omit for used / not_usedis: used one of these codes. not: didn’t use any of them. used: used any code. not_used: used no code.
number_eventssee number_eventsinteger 1–10purchased only.

Example:

{ "field": "ecomm", "op": "purchased",
"filters": [
{ "field": "ecomm_timeframe", "op": "date_within", "value": "30" },
{ "field": "ecomm_product", "op": "is", "value": ["Blue T-Shirt", "Red T-Shirt"] },
{ "field": "number_events", "op": "greater", "value": 2 }
] }
{ "field": "ecomm", "op": "no_purchased",
"filters": [
{ "field": "ecomm_campaign", "op": "is", "value": 1234567 },
{ "field": "ecomm_timeframe", "op": "between", "value": ["2026-01-01", "2026-03-31"] }
] }

Notes:

  • The activity goes in op, not value. {"field": "ecomm", "op": "is", "value": "purchased"} is rejected.
  • With no_purchased, text filters support only is, not, contains and notcontain, and ecomm_order_total supports only is and not. Don’t combine no_purchased with starts / ends or with order total greater / less.
  • With no_purchased and a single ecomm_campaign filter, orders with no attributed campaign count as “not from that campaign”.
  • ecomm_price, ecomm_quantity, ecomm_page_url, ecomm_search and review filters aren’t accepted here.

total_spent — Amount spent in total

Availability: Requires a connected e-commerce store. Scoping filters are Beta (see below). Contacts by the sum of their order totals. Without scoping filters this is the contact’s lifetime total.

Two shapes are accepted.

Simple shape: the comparison is on the condition.

OpMeaningValue
greaterTotal spent is more than the amountmoney
lessTotal spent is less than the amount, including contacts who have never purchasedmoney
isTotal spent equals the amount; 0 also matches contacts who have never purchasedmoney
notTotal spent is not the amount, including contacts who have never purchased (except for not 0, which matches only contacts with a non-zero total)money

Filtered shape: op is is or not (not excludes the contacts the filters describe), with no value. The comparison goes in a filter.

Filters (filtered shape only)

Filter fieldOpsValueNotes
ecomm_total_spent_amountany, is, not, greater, lessmoneyThe comparison. With any or omitted, the condition means “has orders (in scope)”.
ecomm_timeframesee timeframedate or daysBeta. Sums only orders in the timeframe.
ecomm_storeany, is, notBeta store idBeta. Sums only orders from the store.
ecomm_collectionany + text opscollection id or nameBeta. Sums only orders in the collection.

Example:

{ "field": "total_spent", "op": "greater", "value": "250" }
{ "field": "total_spent", "op": "is",
"filters": [
{ "field": "ecomm_total_spent_amount", "op": "greater", "value": "100.00" },
{ "field": "ecomm_timeframe", "op": "date_within", "value": "90" }
] }

Notes:

  • Scoping filters (ecomm_timeframe, ecomm_store, ecomm_collection) aren’t available on every account yet. Where they aren’t available, the segment saves, but requests for its count or members return an error.
  • With scoping filters, is and not compare to the cent.
  • Other filters (for example ecomm_product) are ignored. Don’t send them.
  • "$250" is rejected; send "250".

spent_avg — Average amount spent per order

Availability: Requires a connected e-commerce store. Scoping filters are Beta. Contacts by their average order value. Same two shapes as total_spent.

OpMeaningValue
greaterAverage order value is more than the amountmoney
lessAverage is less than the amount, including contacts who have never purchasedmoney
isAverage equals the amount; 0 also matches contacts who have never purchasedmoney
notAverage is not the amount, including contacts who have never purchased (except for not 0)money

Filtered shape: op is / not, no value.

Filters (filtered shape only)

Filter fieldOpsValueNotes
ecomm_avg_spentany, is, not, greater, lessmoneyThe comparison.
ecomm_timeframesee timeframedate or daysBeta.
ecomm_storeany, is, notBeta store idBeta.
ecomm_collectionany + text opscollection id or nameBeta.

Example:

{ "field": "spent_avg", "op": "less", "value": 40 }
{ "field": "spent_avg", "op": "not",
"filters": [
{ "field": "ecomm_avg_spent", "op": "greater", "value": "75" },
{ "field": "ecomm_timeframe", "op": "date_within", "value": "180" }
] }

Notes:

  • To match zero, send 0 (not 0.00).
  • The scoping-filter rollout note on total_spent applies here too.
  • Only greater, less, is and not are accepted; between is rejected.

orders_count — Total number of orders

Availability: Requires a connected e-commerce store. Scoping filters are Beta. Contacts by how many orders they’ve placed. Same two shapes as total_spent.

OpMeaningValue
greaterMore than N orderswhole number ≥ 0
lessFewer than N orders, including contacts with no orderswhole number ≥ 0
isExactly N orders; 0 also matches contacts with no orderswhole number ≥ 0
notNot N orders, including contacts with no orders (except for not 0)whole number ≥ 0

Filtered shape: op is / not, no value.

Filters (filtered shape only)

Filter fieldOpsValueNotes
ecomm_order_countany, is, not, greater, lesswhole numberThe comparison.
ecomm_timeframesee timeframedate or daysBeta.
ecomm_storeany, is, notBeta store idBeta.

Example:

{ "field": "orders_count", "op": "greater", "value": 3 }
{ "field": "orders_count", "op": "is",
"filters": [
{ "field": "ecomm_order_count", "op": "is", "value": 1 },
{ "field": "ecomm_timeframe", "op": "greater", "value": "2026-06-30" }
] }

Notes:

  • Counts must be whole numbers: 2.5 and 5.0 are rejected.
  • ecomm_collection isn’t supported on a count of orders and is rejected.
  • The scoping-filter rollout note on total_spent applies here too.

ecomm_page_viewed — Page viewed

Availability: Requires a connected e-commerce store. Contacts who did, or didn’t, view a storefront page that meets every filter.

OpMeaningValue
page_viewedViewed at least one matching pageomit
no_page_viewedViewed no matching pageomit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or days
ecomm_storeany, is, notBeta store id
ecomm_page_urlany + text opsURL textThe page URL.

Example:

{ "field": "ecomm_page_viewed", "op": "page_viewed",
"filters": [
{ "field": "ecomm_page_url", "op": "contains", "value": "/collections/sale" },
{ "field": "ecomm_timeframe", "op": "date_within", "value": "14" }
] }

Notes:

  • The op is page_viewed, not viewed.

ecomm_product_viewed — Product viewed

Availability: Requires a connected e-commerce store. Contacts who did, or didn’t, view a product that meets every filter.

OpMeaningValue
viewedViewed at least one matching productomit
no_viewedViewed no matching productomit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or days
ecomm_storeany, is, notBeta store id
ecomm_producttext opsproduct title(s)
ecomm_product_varianttext opsvariant title(s)
ecomm_categorytext opsvendor name(s)
ecomm_collectiontext opscollection id(s) for is/not; name for the others

Example:

{ "field": "ecomm_product_viewed", "op": "viewed",
"filters": [
{ "field": "ecomm_product", "op": "is", "value": "Trail Runner 2" },
{ "field": "ecomm_timeframe", "op": "date_within", "value": "30" }
] }

Notes:

  • There are no price, quantity or total filters on this condition.

ecomm_collection_viewed — Collection viewed

Availability: Requires a connected e-commerce store. Contacts who did, or didn’t, view a collection page that meets every filter.

OpMeaningValue
viewedViewed at least one matching collectionomit
no_viewedViewed no matching collectionomit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or days
ecomm_storeany, is, notBeta store id
ecomm_collectionany + text opscollection id(s) for is/not; name for the othersany means any collection.

Example:

{ "field": "ecomm_collection_viewed", "op": "viewed",
"filters": [ { "field": "ecomm_collection", "op": "contains", "value": "Summer" } ] }

Notes:

  • Product, variant and category filters aren’t accepted here.

ecomm_search_submitted — Search submitted

Availability: Requires a connected e-commerce store. Contacts who did, or didn’t, run a storefront search that meets every filter.

OpMeaningValue
searchedRan at least one matching searchomit
no_searchedRan no matching searchomit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or days
ecomm_storeany, is, notBeta store id
ecomm_searchany + text opssearch textWhat the contact searched for.

Example:

{ "field": "ecomm_search_submitted", "op": "searched",
"filters": [ { "field": "ecomm_search", "op": "contains", "value": "boots" } ] }

Notes:

  • The op is searched, not search_submitted.

ecomm_product_added_to_cart — Product added to cart

Availability: Requires a connected e-commerce store. Contacts who did, or didn’t, add a product to their cart that meets every filter.

OpMeaningValue
product_added_to_cartAdded at least one matching productomit
no_product_added_to_cartAdded no matching productomit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or days
ecomm_storeany, is, notBeta store id
ecomm_producttext opsproduct title(s)
ecomm_product_varianttext opsvariant title(s)
ecomm_categorytext opsvendor name(s)
ecomm_collectiontext opscollection id(s) for is/not; name for the others
ecomm_priceany, is, not, greater, lessmoneyUnit price of the product added.
ecomm_quantityany, is, not, greater, lesswhole numberQuantity added.

Example:

{ "field": "ecomm_product_added_to_cart", "op": "product_added_to_cart",
"filters": [
{ "field": "ecomm_collection", "op": "is", "value": "gid://shopify/Collection/123456789" },
{ "field": "ecomm_quantity", "op": "greater", "value": 1 }
] }

Notes:

  • ecomm_order_total isn’t accepted here; use ecomm_price.

ecomm_checkout_started — Checkout started

Availability: Requires a connected e-commerce store. Contacts who did, or didn’t, start a checkout that meets every filter. Use no_checkout_started together with purchase activity to find abandoned checkouts.

OpMeaningValue
checkout_startedStarted at least one matching checkoutomit
no_checkout_startedStarted no matching checkoutomit

Filters

Filter fieldOpsValueNotes
ecomm_timeframesee timeframedate or days
ecomm_storeany, is, notBeta store id
ecomm_producttext opsproduct title(s)
ecomm_product_varianttext opsvariant title(s)
ecomm_categorytext opsvendor name(s)
ecomm_collectiontext opscollection id(s) for is/not; name for the others
ecomm_quantityany, is, not, greater, lesswhole numberTotal quantity in the checkout.

Example:

{ "field": "ecomm_checkout_started", "op": "checkout_started",
"filters": [
{ "field": "ecomm_timeframe", "op": "date_within", "value": "3" },
{ "field": "ecomm_quantity", "op": "greater", "value": "2" }
] }
{ "match": "all", "conditions": [
{ "field": "ecomm_checkout_started", "op": "checkout_started",
"filters": [ { "field": "ecomm_timeframe", "op": "date_within", "value": "7" } ] },
{ "field": "ecomm", "op": "no_purchased",
"filters": [ { "field": "ecomm_timeframe", "op": "date_within", "value": "7" } ] }
] }

ecomm_review_submitted — Review submitted

Availability: Requires a connected Judge.me or Yotpo reviews integration. Contacts who did, or didn’t, submit a store or product review that meets every filter.

OpMeaningValue
submittedSubmitted at least one matching reviewomit
not_submittedSubmitted no matching reviewomit

Filters

Filter fieldOpsValueNotes
ecomm_review_typeany, site_or_store_review, product_reviewomitThe review type is the op.
ecomm_timeframesee timeframedate or daysWhen the review was submitted.
ecomm_storeany, is, notBeta store id
ecomm_producttext opsproduct title(s)The reviewed product.
ecomm_review_scoreany, is, not, greater, lesswhole number, must be 1–5Star rating.

Example:

{ "field": "ecomm_review_submitted", "op": "submitted",
"filters": [
{ "field": "ecomm_review_type", "op": "product_review" },
{ "field": "ecomm_review_score", "op": "less", "value": 3 }
] }

Notes:

  • {"field": "ecomm_review_type", "op": "is", "value": "product_review"} is rejected; put the type in op.
  • number_events isn’t supported on this condition.

ecomm_back_in_stock_request — Back in stock request

Availability: Requires back-in-stock requests collected through Mailchimp signup forms. Contacts who did, or didn’t, ask to be notified when a product is back in stock.

OpMeaningValue
requestedMade at least one matching requestomit
requested_notMade no matching requestomit

Filters

Filter fieldOpsValueNotes
ecomm_back_in_stock_request_storeis, notBeta store idSame id format as ecomm_store.
ecomm_back_in_stock_request_producttext opsproduct title(s)
ecomm_back_in_stock_request_product_varianttext opsvariant title(s)

Example:

{ "field": "ecomm_back_in_stock_request", "op": "requested",
"filters": [ { "field": "ecomm_back_in_stock_request_product", "op": "is", "value": "Linen Shirt" } ] }

Notes:

  • This condition uses its own filter ids. ecomm_store, ecomm_product, ecomm_timeframe and number_events are rejected.
  • Leave out a filter you don’t need rather than sending it with any.

Churn risk and the legacy customer lifetime value predictions are documented under Predictive insights and integrations.

Predictive insights and integrations

These conditions select contacts by predictions Mailchimp computes from purchase and profile data (purchase likelihood, lifetime value, next order date, churn risk, age and gender), and by activity synced in from connected integrations (lead ads, bookings and QuickBooks Online). Predicted location (ipgeo) and age gating (age_gating) are documented with the contact data conditions.

Prediction freshness (applies to the first four conditions)

predicted_clv, likelihood_to_purchase, time_to_next_purchase and ecomm_churn_risk only consider contacts whose prediction was refreshed in the last 60 days (UTC). A contact whose latest prediction is older than that never matches, whatever the op. You can’t change this window.

predicted_clv — Predicted customer lifetime value

Availability: Requires predictive insights (a connected e-commerce store with enough purchase history).

Selects contacts whose predicted customer lifetime value is above or below an amount in US dollars.

OpMeaningValue
greaterPredicted lifetime value is greater than the valueNumber, required
lessPredicted lifetime value is less than the valueNumber, required
anyContact has a recent prediction. The amount is not checkedOmit

Example:

{ "field": "predicted_clv", "op": "greater", "value": 250 }

Notes:

  • value must be a number 0 or greater, in US dollars. A JSON number or a numeric string ("250") both work.
  • Any other op (for example is) is rejected with Operation must be one of 'any', 'greater', 'less'.

likelihood_to_purchase — Likelihood to purchase

Availability: Requires predictive insights (a connected e-commerce store with enough purchase history).

Selects contacts by a predicted purchase-likelihood score. A higher score means the contact is more likely to purchase.

OpMeaningValue
greaterScore is greater than the valueInteger, required
lessScore is less than the valueInteger, required
anyContact has a recent prediction. The score is not checkedOmit

Example:

{ "field": "likelihood_to_purchase", "op": "greater", "value": 750 }

Notes:

  • value must be an integer from 0 to 1000.
  • The value is a score, not a label: "high" or "low" aren’t valid. Any op other than the three above is rejected with Operation must be one of 'greater', 'less', 'any'.
  • Not the same as clv_lifecycle (the legacy “likelihood to purchase again” condition).

time_to_next_purchase — Predicted next order date

Availability: Requires predictive insights (a connected e-commerce store with enough purchase history).

Selects contacts by the date Mailchimp predicts they’ll place their next order.

OpMeaningValue
anyContact has a predicted next order dateOmit
betweenPredicted date is on or between the two dates (both inclusive)["YYYY-MM-DD", "YYYY-MM-DD"]
greaterPredicted date is after the date"YYYY-MM-DD"
lessPredicted date is before the date"YYYY-MM-DD"
date_withinPredicted date is on or before today plus N daysInteger N, greater than 0
date_notwithinPredicted date is after today plus N daysInteger N, greater than 0

Examples:

{ "field": "time_to_next_purchase", "op": "date_within", "value": 7 }
{ "field": "time_to_next_purchase", "op": "between", "value": ["2026-10-05", "2026-10-31"] }

Notes:

  • Dates and “today” are evaluated in UTC.
  • date_within has no lower bound, so it also matches contacts whose predicted date has already passed. To match only upcoming dates, use between with today’s date as the start.
  • Dates must be YYYY-MM-DD. Any other format fails with Invalid date format: <value>. between takes exactly two dates.
  • A non-integer day count fails with Value must be a valid number for 'within' and 'notwithin' operators, and a count of 0 or less fails with Value must be greater than 0 for 'within' and 'notwithin' operators.
  • Any other op fails with Operation must be any, between, greater, less, date_within, or date_notwithin.

ecomm_churn_risk — Customer churn risk

Availability: Requires predictive insights (a connected e-commerce store with enough purchase history).

Selects contacts by their predicted churn-risk level.

OpMeaningValue
isChurn risk is the valueLOW, MEDIUM or HIGH
notChurn risk is not the valueLOW, MEDIUM or HIGH
anyContact has a churn-risk levelOmit
ValueMeaning
HIGHCustomer unlikely to purchase in the next year
MEDIUMCustomer’s predicted purchase date is later than is typical for your store
LOWCustomer likely to purchase within the next year

Example:

{ "field": "ecomm_churn_risk", "op": "is", "value": "HIGH" }

Notes:

  • Values must be uppercase; "high" is rejected.
  • value is a single string. Arrays are rejected with Churn risk must be one of LOW, MEDIUM, HIGH. To match two levels, put two conditions in a "match": "any" group.
  • Use not for “is not”. is_not and none are rejected.

clv_lifetime_value — Customer lifetime value (legacy)

Availability: Beta. Requires a connected e-commerce store with customer lifetime value predictions.

Selects contacts whose lifetime-value level for one e-commerce store is, or is not, a given level. This is the older store-level prediction. For a dollar amount, use predicted_clv.

OpMeaningValue
isContact’s level for the store is the valuehigh, average or low
notContact’s level for the store is not the value. Contacts with no prediction also matchhigh, average or low
ValueMeaning
highYour highest-valued customers, based on how often they buy and how much they’ve spent
averageCustomers whose predicted future spend is moderate
lowCustomers whose predicted future spend is low

extra (required): the e-commerce store id, as a string. Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the e-commerce store, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change.

Example:

{ "field": "clv_lifetime_value", "op": "is", "value": "high", "extra": "123456" }

Notes:

  • Send values in lowercase. moderate and medium are not valid; use average.
  • A missing extra is rejected with a 400. An empty string is accepted but matches nobody.

clv_lifecycle — Likelihood to purchase again (legacy)

Availability: Beta. Requires a connected e-commerce store with customer lifetime value predictions.

Selects contacts whose repeat-purchase likelihood level for one e-commerce store is, or is not, a given level. For a numeric score, use likelihood_to_purchase.

OpMeaningValue
isContact’s level for the store is the valueSee below
notContact’s level for the store is not the value. Contacts with no prediction also matchSee below
ValueShown in Mailchimp asMeaning
aliveHighHighly likely to buy from you again
riskModerateModerately likely to buy from you again
lapsedLowUnlikely to buy from you again
newNewShown as “New” in Mailchimp

extra (required): the e-commerce store id, as a string. Takes Mailchimp’s internal id, which other API endpoints don’t return. To find it, build an advanced segment in Mailchimp that uses the e-commerce store, read it with GET /3.0/segments/{segment_id}, and copy the value. The format may change.

Example:

{ "field": "clv_lifecycle", "op": "not", "value": "lapsed", "extra": "123456" }

Notes:

  • Send values in lowercase. high, moderate and low are not valid values for this field and are rejected with a 400.
  • A missing extra is rejected with a 400.

age_range — Predicted age range

Availability: Requires predicted demographics to be turned on for the account.

Selects contacts by their predicted age bracket.

OpMeaningValue
isPredicted age range is the valueRequired, see below
notPredicted age range is not the valueRequired, see below
blankContact has no predicted age rangeOmit
blank_notContact has a predicted age rangeOmit

Example:

{ "field": "age_range", "op": "is", "value": "25-34" }

Notes:

  • value must be one of 18-24, 25-34, 35-44, 45-54, 55-64, 65+, as a single string. Other strings are accepted but match nobody, so check the spelling.
  • is or not without a value is rejected with a 400.

gender — Predicted gender

Availability: Requires predicted demographics to be turned on for the account.

Selects contacts by their predicted gender.

OpMeaningValue
isPredicted gender is the valuefemale, male, other or unknown
notPredicted gender is not the valuefemale, male, other or unknown
blankPredicted gender is unknown""
blank_notPredicted gender is anything other than unknown""

Examples:

{ "field": "gender", "op": "is", "value": "female" }
{ "field": "gender", "op": "blank_not", "value": "" }

Notes:

  • Values are case-insensitive. other is shown as “Another identity” in Mailchimp; another_identity is not a valid value.
  • blank means the prediction is unknown, not that the contact has no prediction. Contacts that were never scored don’t match blank.
  • With blank and blank_not, send "value": "".

lead_ad — Lead ad activity

Availability: Requires a connected lead ads integration.

Selects contacts who did (is) or did not (not) come in through a lead ad matching the filters.

OpMeaningValue
isContact has a lead ad response matching all the filtersOmit
notContact has no lead ad response matching all the filtersOmit

Filters (all optional; a contact matches when a single lead ad response satisfies every filter):

Filter fieldOpsValueNotes
form_nameany, is, not, contains, notcontain, starts, endsStringName of the lead ad form
integration_nameany, is, not, contains, notcontain, starts, endsStringName of the lead ads integration the response came from
lead_ad_timeframeany, is, not, greater, less, between, date_within, date_notwithin, campaign_is, campaign_greater, campaign_lessSee belowDate of the response

lead_ad_timeframe values:

  • is, not, greater, less: a date, "YYYY-MM-DD".
  • between: ["YYYY-MM-DD", "YYYY-MM-DD"].
  • date_within, date_notwithin: an integer number of days back from today.
  • campaign_is, campaign_greater, campaign_less: on, after or before the send date of a campaign. The value is the campaign’s web_id from GET /3.0/campaigns (an integer), or "last" for the most recent campaign sent to this audience.

Example:

{
"field": "lead_ad",
"op": "is",
"filters": [
{ "field": "form_name", "op": "contains", "value": "Spring promo" },
{ "field": "lead_ad_timeframe", "op": "date_within", "value": 30 }
]
}

Notes:

  • contains, notcontain, starts and ends on form_name and integration_name are case-insensitive.
  • any on a filter is not a no-op: it requires the response to have a value for that attribute. To leave an attribute unconstrained, omit the filter.
  • lead_ad_timeframe dates are evaluated in the account’s timezone. Any extra you send on it is replaced.
  • A campaign op fails with No valid campaigns found if the campaign hasn’t been sent to this audience.
  • The filter is lead_ad_timeframe, not timeframe. Unknown filter fields fail with Unsupported operation: <field>.

booking_activity — Booking activity

Availability: Requires a connected booking integration that syncs bookings to Mailchimp.

Selects contacts who have (or have no) booking matching the filters.

OpMeaningValue
booking_activityContact has a booking matching all the filtersOmit
no_booking_activityContact has no booking matching all the filtersOmit

Filters (all optional; a single booking must satisfy every filter):

Filter fieldOpsValueNotes
booking_created_dateany, is, not, greater, less, between, date_within, date_notwithin, campaign_is, campaign_greater, campaign_lessSame as lead_ad_timeframeWhen the booking was made. any adds no constraint
booking_start_dateSame as booking_created_dateSame as lead_ad_timeframeWhen the booked service starts. any adds no constraint
booking_service_typeany, is, notOne of APPOINTMENT, CLASS, COURSE, SERVICE, SERIES, GROUP, SOLOUppercase, single value
booking_service_nameany, is, not, contains, notcontain, starts, endsStringName of the booked service
booking_service_categoryany, is, not, contains, notcontain, starts, endsStringCategory of the booked service

Examples:

{
"field": "booking_activity",
"op": "booking_activity",
"filters": [
{ "field": "booking_service_type", "op": "is", "value": "APPOINTMENT" },
{ "field": "booking_start_date", "op": "date_within", "value": 30 }
]
}
{ "field": "booking_activity", "op": "no_booking_activity",
"filters": [ { "field": "booking_created_date", "op": "date_within", "value": 90 } ] }

Notes:

  • booking_service_type values must be uppercase and a single string; "appointment" is rejected.
  • any on booking_service_type, booking_service_name or booking_service_category requires the booking to have a value for that attribute. To leave it unconstrained, omit the filter.
  • Campaign ops take the campaign’s web_id from GET /3.0/campaigns (an integer), or "last".
  • no_booking_activity needs at least one filter; without one it is rejected.
  • Any other top-level op fails with Operation must be booking_activity or no_booking_activity.

qbo_invoice_activity — QuickBooks Online invoice activity

Availability: Requires the QuickBooks Online integration, with contact sync turned on for the audience.

Selects contacts who have (or don’t have) a QuickBooks Online invoice matching the filters.

OpMeaningValue
qbo_has_invoiceContact has an invoice matching all the filtersOmit
qbo_no_invoiceContact has no invoice matching all the filtersOmit

Filters (all optional; a single invoice must satisfy every filter):

Filter fieldOpsValueNotes
qbo_timeframeany, is, not, greater, less, between, date_within, date_notwithin, campaign_is, campaign_greater, campaign_lessSame as lead_ad_timeframeInvoice transaction date
qbo_productany, is, not, contains, notcontain, starts, endsStringName of a line item on the invoice. any adds no constraint
qbo_order_totalany, is, not, greater, lessNumberInvoice total in your home currency. any adds no constraint
qbo_payment_statusany, isArray of statuses (see below)is means “is one of”. any adds no constraint
Payment statusMeaning
paidPaid
partially_paidPartially paid
not_paid_no_reminderNot paid and hasn’t received a reminder
not_paid_with_reminderNot paid and has received a reminder
overdueDue date has passed and a balance is still outstanding

Examples:

{
"field": "qbo_invoice_activity",
"op": "qbo_has_invoice",
"filters": [
{ "field": "qbo_timeframe", "op": "date_within", "value": 90 },
{ "field": "qbo_order_total", "op": "greater", "value": 100 },
{ "field": "qbo_payment_status", "op": "is", "value": ["paid", "partially_paid"] }
]
}
{
"field": "qbo_invoice_activity",
"op": "qbo_has_invoice",
"filters": [ { "field": "qbo_payment_status", "op": "is", "value": ["overdue"] } ]
}

Notes:

  • Always send qbo_payment_status as an array, even for one status. Status values are lowercase.
  • overdue may be combined with other statuses in one filter, for example ["paid", "overdue"]; the condition matches invoices in any of them.
  • An unknown status is rejected with a 400 that lists the valid statuses.
  • Campaign ops take the campaign’s web_id from GET /3.0/campaigns (an integer), or "last".
  • Any other top-level op fails with Operation must be qbo_has_invoice or qbo_no_invoice.

qbo_sales_receipt_activity — QuickBooks Online sales receipt activity

Availability: Requires the QuickBooks Online integration, with contact sync turned on for the audience.

Selects contacts who have (or haven’t) purchased through a QuickBooks Online sales receipt matching the filters.

OpMeaningValue
qbo_purchasedContact has a sales receipt matching all the filtersOmit
qbo_notpurchasedContact has no sales receipt matching all the filtersOmit

Filters (all optional; a single sales receipt must satisfy every filter): qbo_timeframe, qbo_product and qbo_order_total, with the same ops and values as on qbo_invoice_activity, applied to the sales receipt. qbo_payment_status isn’t available here.

Example:

{
"field": "qbo_sales_receipt_activity",
"op": "qbo_purchased",
"filters": [
{ "field": "qbo_product", "op": "is", "value": "Gift Card" },
{ "field": "qbo_timeframe", "op": "between", "value": ["2026-01-01", "2026-03-31"] }
]
}

Notes:

  • The ops differ from invoices: qbo_has_invoice is rejected here with Operator must be qbo_purchased or qbo_notpurchased.

Events

Event conditions select contacts by the events recorded for them: contact events you post to a member with the Events API (contact_event), and custom events that have a namespace, an event name and typed properties (custom_event_*). This section also covers number_events, the filter that turns “did this at least once” into “did this exactly, more than, or fewer than N times” on activity conditions.

contact_event — Custom engagement

Availability: Generally available

Selects contacts who have, or have not, had at least one contact event that matches all of the condition’s filters. Contact events are the events you post with POST /3.0/lists/{list_id}/members/{subscriber_hash}/events. Every filter must match the same event: name, time and properties are checked together on one event, not across several.

OpMeaningValue
isThe contact has at least one event that matches every filter.Omit
notThe contact has no event that matches every filter. Contacts with no events at all match.Omit

Filters

Filter fieldOpsValueNotes
contact_event_nameis, not, contains, notcontainNon-empty string: the event name exactly as you posted it (for example "signed_up").contains and notcontain match a substring and ignore case. not means “an event with a different name”, not “never had this event”; see Notes. any is not accepted on this filter; leave the filter out instead.
contact_event_timeframeany, is, not, greater, less, between, date_withinDepends on op; see the table below.When the event happened. Leave out extra.
contact_event_propertyany, is, not, contains, notcontainvalue: the property key (string, exact match). extra: the property value, as a string or an array of strings.extra is required for every op except any. See the table below.

You can include a filter field more than once. For example, two contact_event_property filters require one event to have both key/value pairs.

contact_event_timeframe ops:

OpMeaningValue
anyNo time restriction.Omit
isThe event happened on that calendar day (00:00:00 to 23:59:59).Date string
notThe event did not happen on that day.Date string
greaterThe event happened after that day (after 23:59:59 on the date).Date string
lessThe event happened before that day (before 00:00:00 on the date).Date string
betweenThe event happened from the start of the first date through the end of the second date, inclusive.Array of exactly 2 date strings: ["start", "end"]
date_withinThe event happened in the last N days, from the start of the day N days ago through the end of today.Integer number of days (a number or a numeric string), or one of the tokens 7days, 1month, 3months, last18month

contact_event_property ops (value is always the key, matched exactly):

OpMeaningextra
anyNo property restriction.Omit
isThe event has property value, and that property’s value equals extra. With an array, it equals any of the items.String or array of strings
notThe event has property value, and that property’s value is not extra. With an array, it is none of the items.String or array of strings
containsThe property’s value contains extra, ignoring case. With an array, it contains any of the items.String or array of strings
notcontainThe property’s value contains none of the items in extra.String or array of strings

Example: contacts who had a signed_up event on the pricing page in the last 30 days.

{
"field": "contact_event",
"op": "is",
"filters": [
{ "field": "contact_event_name", "op": "is", "value": "signed_up" },
{ "field": "contact_event_timeframe", "op": "date_within", "value": 30 },
{ "field": "contact_event_property", "op": "is", "value": "page", "extra": "pricing" }
]
}

Example: contacts who had no trial_started event during 2025.

{
"field": "contact_event",
"op": "not",
"filters": [
{ "field": "contact_event_name", "op": "is", "value": "trial_started" },
{ "field": "contact_event_timeframe", "op": "between", "value": ["2025-01-01", "2025-12-31"] }
]
}

Notes:

  • Put the property value in extra, not in value. {"field": "contact_event_property", "op": "is", "value": "plan=gold"} is rejected because extra is missing. Write "value": "plan", "extra": "gold" instead.
  • To find contacts who never had an event, use "op": "not" on the contact_event condition with contact_event_name is. Putting not on contact_event_name with "op": "is" on the condition selects contacts who had some other event.
  • Dates must be YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS±HH:MM. Any other format is rejected. Dates are interpreted in UTC.
  • between needs exactly two dates.
  • Don’t send value, value_op or extra on the contact_event condition itself.
  • contact_event_name, contact_event_timeframe and contact_event_property work only as filters of contact_event. Used as a top-level field, they are rejected.
  • number_events is not supported on contact_event.

custom_event_* — Custom event

Availability: Requires custom events in the audience

Selects contacts who have, or have not, had at least one custom event with a given namespace and event name. Property filters can narrow the match by the event’s typed properties. The namespace, the event name and every property filter must match the same event.

  • Namespace: the group the event belongs to, usually the integration or system that sends it (for example loyalty).
  • Event name: the event type within that namespace (for example rewards-redeemed).

Field id: custom_event_ + the namespace in lowercase with spaces replaced by - + _ + the event name. For namespace Loyalty and event rewards-redeemed, the field id is custom_event_loyalty_rewards-redeemed. Mailchimp uses the field id to look up the event’s property schema. The event to match is the one named by namespace and event_name.

OpMeaningValue
isThe contact has had at least one matching event.Omit
notThe contact has had no matching event.Omit

Condition keys

KeyValueNotes
namespaceString: the event’s namespace, as sent with the event (for example "loyalty").Required in the canonical form.
event_nameString: the event name (for example "rewards-redeemed").Required in the canonical form.

Filters

Filter fieldOpsValueNotes
custom_event_property_<property>Depends on type; see the table below.Depends on type.<property> is the property name from the event’s schema. Each property filter must include type.
custom_event_namespaceisNon-empty stringAlternative to the namespace key.
custom_event_nameisNon-empty stringAlternative to the event_name key.

Property filter types and ops:

typeOpsValue
stringany, is, not, contains, startsString. is and not also take an array of strings (matches any of them / none of them). contains and starts take a single string and ignore case.
integerany, is, not, greater, lessNumber. Must be numeric.
decimalany, is, not, greater, lessNumber.
booleanany, is, not"true" or "false".
datetimeany, is, not, greater, less, between, date_withinSame formats as contact_event_timeframe: a date string; between takes an array of exactly 2 dates; date_within takes a number of days or a token (7days, 1month, 3months). Evaluated in UTC.

greater and less are strict (greater than / less than). any means no restriction on that property.

Example: contacts who redeemed a loyalty reward worth more than 500 points.

{
"field": "custom_event_loyalty_rewards-redeemed",
"op": "is",
"namespace": "loyalty",
"event_name": "rewards-redeemed",
"filters": [
{ "field": "custom_event_property_points", "op": "greater", "value": 500, "type": "integer" }
]
}

Example: contacts who have never redeemed a loyalty reward, using the identity filters instead of the condition keys.

{
"field": "custom_event_loyalty_rewards-redeemed",
"op": "not",
"filters": [
{ "field": "custom_event_namespace", "op": "is", "value": "loyalty" },
{ "field": "custom_event_name", "op": "is", "value": "rewards-redeemed" }
]
}

Notes:

  • Always identify the event. Either set namespace and event_name on the condition (the canonical form, which is how segments are read back), or add both the custom_event_namespace and custom_event_name filters. Use one form, not both.
  • A property filter without type, or with a type other than the five listed, is rejected.
  • Property values must also meet the constraints in the event’s schema, such as allowed values, minimum and maximum, and length or pattern.
  • Custom events have no separate timeframe filter. To filter by time, use a datetime property.
  • number_events is not supported on custom events.
  • Don’t send value, value_op or extra on the condition itself.

number_events — Number of times (filter)

Availability: Generally available

A filter, not a top-level condition. Add it to the filters of a supported activity condition to require that the contact performed the activity exactly, more than, or fewer than N times. Without it, those conditions mean “at least once”.

OpMeaningValue
at_least_once1 or more times. This is the same as leaving the filter out.Omit
isExactly N times.Integer from 1 to 10
greaterMore than N times (strict: greater 3 means 4 or more).Integer from 1 to 10
lessFewer than N times (strict: less 3 means 1 or 2, because the activity condition still requires at least one).Integer from 1 to 10

Supported parent conditions:

Parent fieldParent ops that accept number_eventsCounts
email_campaign_activitysent, open, clickEmails sent, opens, or clicks
sms_campaign_activitysent, clickSMS messages sent, or link clicks
whatsapp_campaign_interactionsent, clickWhatsApp messages sent, or link clicks
ecommpurchasedOrders

Example: contacts who purchased exactly twice.

{
"field": "ecomm",
"op": "purchased",
"filters": [
{ "field": "number_events", "op": "is", "value": 2 }
]
}

Example: contacts who opened emails at least 5 times (written as more than 4).

{
"field": "email_campaign_activity",
"op": "open",
"filters": [
{ "field": "number_events", "op": "greater", "value": 4 }
]
}

Notes:

  • value must be a single integer from 1 to 10. Arrays, decimals, and numbers outside that range are rejected. For “at least N”, use greater with N − 1.
  • Use at most one number_events filter per condition. A segment can still contain several conditions that each have their own number_events.
  • number_events is rejected on negative parent ops (for example no_open, no_purchased, no_page_viewed, no_viewed), on email_campaign_activity op reply, and on sms_campaign_activity ops delivered and used_keyword.
  • On email_campaign_activity with op open, you can’t combine a counting number_events (is, greater or less) with an open_type filter other than any.
  • number_events is not supported on contact_event or custom_event_*, and it is rejected as a top-level field.
  • The count is the number of times the contact performed the activity.