MOLTED EMAIL

Segmentation

Create dynamic contact segments with filter groups, nested logic, and async computation.

Segments let you group contacts based on filters - contact fields, account data, metadata, firmographic attributes, and behavioral events. Segments are computed asynchronously and can be used for targeting in journeys and experiments.

Create a segment

molted segments create \
  --name "Enterprise customers in US" \
  --filters '{
    "logic": "and",
    "filters": [
      { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "customer" },
      { "type": "metadata", "field": "region", "operator": "eq", "value": "us-west" },
      { "type": "firmographic", "field": "companySize", "operator": "gte", "value": 500 }
    ]
  }'
FlagTypeRequiredDescription
--namestringYesSegment name.
--filtersJSONYesFilter group as JSON. See filter reference below.
POST https://api.molted.email/v1/segments
curl
curl -X POST https://api.molted.email/v1/segments \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Enterprise customers in US",
    "filterGroup": {
      "logic": "and",
      "filters": [
        { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "customer" },
        { "type": "metadata", "field": "region", "operator": "eq", "value": "us-west" },
        { "type": "firmographic", "field": "companySize", "operator": "gte", "value": 500 }
      ]
    }
  }'
FieldTypeRequiredDescription
namestringYesSegment name.
filterGroupobjectYesFilter group object. See filter reference below.

Get a segment

molted segments get seg_abc123
GET https://api.molted.email/v1/segments/:id
curl
curl "https://api.molted.email/v1/segments/seg_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

List segments

molted segments list
GET https://api.molted.email/v1/segments
curl
curl "https://api.molted.email/v1/segments" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

Returns an array of active segments. Archived segments are excluded.

Response
[
  {
    "id": "seg_abc123",
    "tenant_id": "tenant_abc123",
    "name": "Enterprise customers in US",
    "filter_group": { "logic": "and", "filters": [ "..." ] },
    "status": "active",
    "contact_count": 142,
    "snapshot_version": 3,
    "created_at": "2026-03-01T12:00:00Z",
    "updated_at": "2026-03-15T08:30:00Z"
  }
]

If you have no segments yet, the response is an empty array:

Empty response
[]

No segments yet? Create your first segment with molted segments create. See creating segments above for filter syntax and examples.

Update a segment

molted segments update seg_abc123 \
  --name "Enterprise US (updated)" \
  --filters '{
    "logic": "and",
    "filters": [
      { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "customer" },
      { "type": "metadata", "field": "region", "operator": "in", "value": ["us-west", "us-east"] }
    ]
  }'
FlagTypeRequiredDescription
--namestringNoUpdated segment name.
--filtersJSONNoUpdated filter group as JSON.
PATCH https://api.molted.email/v1/segments/:id
curl
curl -X PATCH https://api.molted.email/v1/segments/seg_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Enterprise US (updated)",
    "filterGroup": {
      "logic": "and",
      "filters": [
        { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "customer" },
        { "type": "metadata", "field": "region", "operator": "in", "value": ["us-west", "us-east"] }
      ]
    }
  }'

Archive a segment

molted segments archive seg_abc123
DELETE https://api.molted.email/v1/segments/:id
curl
curl -X DELETE "https://api.molted.email/v1/segments/seg_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Compute segment membership

Trigger an async recomputation of the segment's current members. Each computation creates a point-in-time snapshot of matching contacts.

molted segments compute seg_abc123
POST https://api.molted.email/v1/segments/:id/compute
curl
curl -X POST "https://api.molted.email/v1/segments/seg_abc123/compute" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

List segment members

Results are paginated. Use limit and offset to page through members.

molted segments members seg_abc123 --limit 50 --offset 0
FlagTypeRequiredDescription
--limitnumberNoMax results per page (default 50).
--offsetnumberNoPagination offset (default 0).
GET https://api.molted.email/v1/segments/:id/members
curl
curl "https://api.molted.email/v1/segments/seg_abc123/members?limit=50&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"

Get contact segments

List all segments a contact belongs to. This is a reverse lookup -- given a contact, it returns every segment they are a member of.

To check whether a contact is in one specific segment instead, use analytics segment-check.

molted segments contact con_abc123
GET https://api.molted.email/v1/segments/contact/:contactId/segments
curl
curl "https://api.molted.email/v1/segments/contact/con_abc123/segments" \
  -H "Authorization: Bearer YOUR_API_KEY"

Filter types

Each filter has a type that determines which fields you can query.

TypeDescriptionQueryable fields
contact_fieldFilter on contact properties.email, name, ownerEmail, lifecycleStage, dealStage
account_fieldFilter on the contact's linked account.name, domain, plus any key in the account's metadata object
metadataFilter on contact custom metadata.Any key in the contact's metadata object
firmographicFilter on account custom metadata.Any key in the account's metadata object
behavioralFilter on event counts within a time window.Uses behavioralWindow - see behavioral filters below

Standard filter structure

{
  "type": "contact_field",
  "field": "lifecycleStage",
  "operator": "eq",
  "value": "customer"
}
FieldTypeRequiredDescription
typestringYesOne of: contact_field, account_field, metadata, firmographic, behavioral.
fieldstringYesThe field to filter on. Valid fields depend on the type.
operatorstringYesComparison operator. See operators below.
valueanyVariesThe value to compare against. Not required for exists/not_exists.

Behavioral filters

Behavioral filters count how many times an event occurred within a time window. They use a behavioralWindow object instead of a simple value.

{
  "type": "behavioral",
  "field": "event_count",
  "operator": "gte",
  "value": 0,
  "behavioralWindow": {
    "eventName": "email_opened",
    "windowDays": 30,
    "countOperator": "gte",
    "countValue": 3
  }
}
FieldTypeRequiredDescription
behavioralWindow.eventNamestringYesThe event to count (e.g. email_opened, email_clicked, email_sent).
behavioralWindow.windowDaysnumberYesLookback window in days. Maximum 90.
behavioralWindow.countOperatorstringYesOperator to apply to the event count (e.g. gte, eq, lt).
behavioralWindow.countValuenumberYesThe threshold count to compare against.

This example matches contacts who opened an email 3 or more times in the last 30 days.

Operators

OperatorValue typeDescriptionExample value
eqanyEquals."pro", 500, true
neqanyNot equals."free"
gtnumberGreater than.100
gtenumberGreater than or equal.500
ltnumberLess than.50
ltenumberLess than or equal.1000
containsstringString contains substring."example.com"
not_containsstringString does not contain substring."test"
inarrayValue is in the provided list.["us-west", "us-east"]
not_inarrayValue is not in the provided list.["spam", "bounced"]
existsnoneField exists and is not null. No value needed.-
not_existsnoneField does not exist or is null. No value needed.-
betweenarrayValue is between two bounds (inclusive).[100, 500]

Type constraints: gt, gte, lt, lte, and between only work with numeric values. contains and not_contains only work with strings. Using an operator with the wrong value type returns no matches.

Filter group structure

A filter group wraps one or more filters with a logic operator.

{
  "logic": "and",
  "filters": [
    { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "customer" },
    { "type": "metadata", "field": "region", "operator": "eq", "value": "us-west" }
  ]
}
FieldTypeRequiredDescription
logicstringYesand or or. Determines how filters are combined.
filtersarrayYesArray of filters or nested filter groups.

Nested logic

Filter groups can contain other filter groups for complex AND/OR logic:

Nested filter group
{
  "logic": "or",
  "filters": [
    {
      "logic": "and",
      "filters": [
        { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "lead" },
        {
          "type": "behavioral",
          "field": "event_count",
          "operator": "gte",
          "value": 0,
          "behavioralWindow": {
            "eventName": "email_opened",
            "windowDays": 30,
            "countOperator": "gte",
            "countValue": 3
          }
        }
      ]
    },
    {
      "logic": "and",
      "filters": [
        { "type": "contact_field", "field": "lifecycleStage", "operator": "eq", "value": "customer" },
        { "type": "metadata", "field": "plan", "operator": "eq", "value": "enterprise" }
      ]
    }
  ]
}

This matches contacts who are either (leads with 3+ email opens in the last 30 days) OR (enterprise customers). Nesting depth is unlimited.

  • Contacts - manage the contacts that segments filter on
  • Analytics - check segment membership with segment-check
  • Journeys - use segment IDs as journey trigger conditions