MailLandDocs

Segments

Create dynamic segments based on subscriber attributes and behavior

Segments are dynamic subscriber groups defined by conditions. Unlike static lists, segments automatically update as subscriber data changes. Use segments to target campaigns at specific audiences based on attributes, engagement, and behavior.

Match Types

Match TypeValueDescription
All0All conditions must match (AND logic)
Any1Any condition can match (OR logic)

Create a Segment

POST https://api.mail.land/v1/marketing/segments
Create segment request
{
  "name": "Active Engaged Users",
  "description": "Users who opened or clicked in last 30 days",
  "matchType": "All",
  "conditions": [
    {
      "field": "lastemailopenedat",
      "operator": "inlast",
      "value": "30"
    },
    {
      "field": "status",
      "operator": "equals",
      "value": "Active"
    }
  ]
}
FieldTypeRequiredDescription
namestringYesSegment name (unique per workspace)
descriptionstringNoSegment description
matchTypestringNoAll (default) or Any
conditionsarrayYesAt least one condition
Create a segment
curl -X POST https://api.mail.land/v1/marketing/segments \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Active Engaged Users",
    "matchType": "All",
    "conditions": [
      { "field": "lastemailopenedat", "operator": "inlast", "value": "30" },
      { "field": "status", "operator": "equals", "value": "Active" }
    ]
  }'

Response

Segment response
{
  "id": "0qe306asbapwvd",
  "name": "Active Engaged Users",
  "description": "Users who opened or clicked in last 30 days",
  "matchType": "all",
  "matchTypeName": "All",
  "conditionsCount": 2,
  "subscriberCount": 450,
  "createdAt": "2026-02-17T12:00:00Z",
  "updatedAt": "2026-02-17T12:00:00Z"
}

Responses return matchType in lowercase ("all" / "any") even though the create/update request accepts "All"/"Any".

Condition fields based on opens/clicks (emailsopened, lastemailopenedat, etc.) include machine activity, Apple Mail Privacy Protection prefetch and security link scanners, which is not filtered out today.

An undocumented GET /{id}/preview endpoint also exists, returning a sample of subscribers who currently match the segment's conditions.

Condition Fields

String Fields

Fields: email, firstname, lastname, company, source, phone

OperatorDescriptionValue Required
equalsExact matchYes
notequalsNot equalYes
containsContains substringYes
notcontainsDoes not containYes
startswithStarts withYes
endswithEnds withYes
isemptyField is emptyNo
isnotemptyField is not emptyNo

Numeric Fields

Fields: emailssent, emailsopened, emailsclicked

OperatorDescriptionValue RequiredValue2 Required
equalsEqual toYesNo
notequalsNot equalYesNo
greaterthanGreater thanYesNo
greaterthanorequalGreater or equalYesNo
lessthanLess thanYesNo
lessthanorequalLess or equalYesNo
betweenBetween two valuesYesYes

Date Fields

Fields: createdat, subscribedat, lastemailsentat, lastemailopenedat, lastemailclickedat

OperatorDescriptionValue Required
equalsOn specific dateYes (ISO date)
beforeBefore dateYes (ISO date)
afterAfter dateYes (ISO date)
onorbeforeOn or beforeYes (ISO date)
onorafterOn or afterYes (ISO date)
betweenBetween datesYes (value + value2)
inlastIn the last N daysYes (integer days)
isnullDate not setNo
isnotnullDate is setNo

Enum Fields

Field: status

OperatorDescriptionValues
equalsEqual to statusActive, Unsubscribed, Bounced, Complained
notequalsNot equal toSame values

Condition Examples

Email domain filter
{ "field": "email", "operator": "contains", "value": "example.com" }
High engagement filter
{ "field": "emailssent", "operator": "between", "value": "10", "value2": "50" }
Recent clickers
{ "field": "lastemailclickedat", "operator": "inlast", "value": "7" }
Missing first name
{ "field": "firstname", "operator": "isempty" }

Get Segment Metadata

Retrieve all available fields, operators, and enum values for building segment conditions:

GET https://api.mail.land/v1/marketing/segments/metadata/fields
Get segment metadata
curl https://api.mail.land/v1/marketing/segments/metadata/fields \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Metadata response
{
  "fields": [
    {
      "name": "email",
      "label": "Email",
      "type": "string",
      "operators": ["equals", "notequals", "contains", "notcontains", "startswith", "endswith", "isempty", "isnotempty"],
      "enumValues": null
    },
    {
      "name": "status",
      "label": "Status",
      "type": "enum",
      "operators": ["equals", "notequals"],
      "enumValues": ["Active", "Unsubscribed", "Bounced", "Complained"]
    }
  ]
}

List Segments

GET https://api.mail.land/v1/marketing/segments
ParameterTypeDefaultDescription
cursorstring-Opaque cursor from the previous page's nextCursor. Omit for the first page.
limitint20Items per page
searchstring-Search by name or description
sortBystring-Sort field
sortDescboolfalseSort descending
List segments
curl "https://api.mail.land/v1/marketing/segments?limit=20" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Get Segment Details

GET https://api.mail.land/v1/marketing/segments/{id}

Returns the full segment with conditions:

Get segment details
curl https://api.mail.land/v1/marketing/segments/0qe306asbapwvd \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Segment detail response
{
  "id": "0qe306asbapwvd",
  "name": "Active Engaged Users",
  "description": "Users who engaged in last 30 days",
  "matchType": "all",
  "matchTypeName": "All",
  "conditionsCount": 2,
  "subscriberCount": 450,
  "conditions": [
    {
      "field": "lastemailopenedat",
      "operator": "inlast",
      "value": "30",
      "value2": null
    },
    {
      "field": "status",
      "operator": "equals",
      "value": "Active",
      "value2": null
    }
  ],
  "cachedCount": 450,
  "cachedAt": "2026-02-17T10:00:00Z",
  "createdAt": "2026-01-10T08:00:00Z",
  "updatedAt": "2026-02-17T10:00:00Z"
}

Preview Conditions

Preview the result of conditions before creating a segment. Segment evaluation always restricts to Active subscribers, so a condition like status notequals Active matches nobody.

POST https://api.mail.land/v1/marketing/segments/preview
Preview request
{
  "conditions": [
    { "field": "lastemailopenedat", "operator": "inlast", "value": "30" }
  ],
  "matchType": "All"
}
Preview segment conditions
curl -X POST https://api.mail.land/v1/marketing/segments/preview \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "conditions": [
      { "field": "lastemailopenedat", "operator": "inlast", "value": "30" }
    ],
    "matchType": "All"
  }'
Preview response
{
  "count": 450,
  "sampleEmails": [
    "[email protected]",
    "[email protected]",
    "[email protected]"
  ]
}

Get Segment Count

GET https://api.mail.land/v1/marketing/segments/{id}/count
Get segment count
curl https://api.mail.land/v1/marketing/segments/0qe306asbapwvd/count \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Count response
{
  "segmentId": "0qe306asbapwvd",
  "count": 450
}

Refresh Segment Cache

Force a re-count of matching subscribers:

POST https://api.mail.land/v1/marketing/segments/{id}/refresh
Refresh segment cache
curl -X POST https://api.mail.land/v1/marketing/segments/0qe306asbapwvd/refresh \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Refresh response
{
  "segmentId": "0qe306asbapwvd",
  "count": 460,
  "refreshedAt": "2026-02-17T12:30:00Z"
}

Duplicate a Segment

POST https://api.mail.land/v1/marketing/segments/{id}/duplicate?name=Copy%20of%20Segment

Creates a new segment with cloned conditions. The name parameter is optional.

Duplicate a segment
curl -X POST "https://api.mail.land/v1/marketing/segments/0qe306asbapwvd/duplicate?name=Copy%20of%20Segment" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Update a Segment

PUT https://api.mail.land/v1/marketing/segments/{id}

The request body matches the create request. Updating a segment automatically refreshes its cached count.

Update a segment
curl -X PUT https://api.mail.land/v1/marketing/segments/0qe306asbapwvd \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Active Engaged Users (Updated)",
    "matchType": "All",
    "conditions": [
      { "field": "lastemailopenedat", "operator": "inlast", "value": "14" },
      { "field": "status", "operator": "equals", "value": "Active" }
    ]
  }'

Delete a Segment

DELETE https://api.mail.land/v1/marketing/segments/{id}

Deleting a segment detaches it from any Draft or Scheduled campaign that targets it (the campaign's segmentId is cleared), which then has no audience: sending it returns 422 or delivers to nobody. A campaign that is already Sending is unaffected, because its recipients were already resolved.

Delete a segment
curl -X DELETE https://api.mail.land/v1/marketing/segments/0qe306asbapwvd \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Error Responses

StatusCodeDescription
400VALIDATION_FAILEDName or conditions invalid
400INVALID_REQUESTSegment name already exists
403FORBIDDENInsufficient permissions
404RESOURCE_NOT_FOUNDSegment not found

Next Steps

  • Campaigns: target campaigns with segments
  • Automations: automations do not currently trigger on segment membership
  • Subscribers: manage the contacts in your segments

On this page