Segments API
Segments define audience groups using a filter DSL. Flows can target a segment so that only matching contacts enter the flow when a trigger event fires.
For a user guide on building segments in the dashboard, see Segments.
Endpoints
CRUD
| Method | Path | Description |
|---|---|---|
GET | /v1/segments | List all segments |
POST | /v1/segments | Create a segment |
GET | /v1/segments/{id} | Get a segment |
PUT | /v1/segments/{id} | Full update |
PATCH | /v1/segments/{id} | Partial update |
DELETE | /v1/segments/{id} | Delete a segment |
Actions
| Method | Path | Description |
|---|---|---|
POST | /v1/segments/{id}/archive | Archive a segment |
POST | /v1/segments/{id}/unarchive | Restore an archived segment |
POST | /v1/segments/{id}/duplicate | Duplicate a segment |
POST | /v1/segments/{id}/evaluate | Re-evaluate membership |
POST | /v1/segments/estimate | Estimate size without saving |
Read-Only
| Method | Path | Description |
|---|---|---|
GET | /v1/segments/{id}/contacts | List matching contacts (paginated) |
GET | /v1/segments/{id}/history | Membership trend over time |
GET | /v1/segments/{id}/usage | Which flows use this segment |
List Segments
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
search | string | -- | Search by name or description (case-insensitive) |
is_archived | boolean | false | Set to true to list archived segments instead |
Response
Create a Segment
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Segment name (1--255 chars) |
description | string | No | Human-readable description |
filters | object | Yes | Filter DSL with all (AND) or any (OR) grouping. See Filter DSL. |
exclusion_rules | array | No | List of filter rules. Contacts matching any exclusion rule are removed. Default: [] |
is_dynamic | boolean | No | Whether the segment recalculates automatically. Default: true |
tags | string[] | No | Freeform tags for organizing segments. Default: [] |
Response (201 Created)
Returns the full segment object (same shape as List response).
Get a Segment
Returns the full segment object.
Update a Segment
Both PUT (full update) and PATCH (partial update) are supported. Both accept the same request body -- PATCH only applies provided fields, while PUT replaces all fields.
Updatable Fields
| Field | Type | Description |
|---|---|---|
name | string | Segment name |
description | string | Description |
filters | object | Filter DSL |
exclusion_rules | array | Exclusion rules |
is_dynamic | boolean | Dynamic recalculation |
tags | string[] | Tags |
Delete a Segment
Response
You cannot delete a segment that is referenced by an active flow. The API returns 409 Conflict in that case. Deactivate the flow first, or archive the segment instead. Non-active flows referencing the segment will have their segment_id cleared automatically.
Archive / Unarchive
Archive a segment you are not currently using. Archived segments are hidden from the default list view but can be restored at any time.
Archive
Unarchive
Both return the updated segment object. The is_archived field reflects the new state.
Duplicate a Segment
Create a copy of an existing segment with (copy) appended to the name. The duplicate inherits all filters, exclusion rules, tags, and settings.
Response (201 Created)
Returns the new segment object. The cached_count and last_evaluated fields are null until the duplicate is evaluated.
Evaluate a Segment
Re-run the segment filters against the contacts table and return the matching count and contact IDs. Also updates the segment's cached_count and last_evaluated fields, and records a history point for the trend graph.
Response
For large segments, the contact_ids array can be substantial. Use the List Contacts endpoint for paginated access.
Estimate Size
Preview how many contacts would match a set of filters without creating or saving a segment. Returns the total count plus per-rule match counts for the segment builder's real-time feedback.
Response
| Field | Type | Description |
|---|---|---|
count | integer | Total contacts matching all filters minus exclusions |
per_rule_counts | integer[] | How many contacts each individual rule matches (in order). Useful for showing per-rule counts in the UI. |
List Matching Contacts
Get a paginated list of contacts that match a segment's filters.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (starts at 1) |
page_size | integer | 20 | Items per page (1--100) |
Response
Segment contacts are evaluated in real time against the current data. For large segments (10,000+ contacts), use the evaluate endpoint first to check the count.
Membership History
View how a segment's size has changed over time. Each data point is recorded whenever the segment is evaluated (manually or by the scheduler).
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
days | integer | 30 | Number of days of history (1--365) |
Response
Segment Usage
See which flows reference a given segment.
Response
Check segment usage before deleting or significantly changing a segment's filters. Active flows that depend on the segment will be affected.
Filter DSL
Segments use a JSON filter DSL with all (AND) and any (OR) grouping:
AND (all conditions must match)
OR (any condition can match)
Filter Operators
| Operator | SQL Equivalent | Applicable Types | Example |
|---|---|---|---|
is | = value | string, number | {"field": "status", "operator": "is", "value": "active"} |
is_not | != value | string, number | {"field": "status", "operator": "is_not", "value": "churned"} |
in | IN (values) | string, number | {"field": "plan", "operator": "in", "value": ["growth", "enterprise"]} |
not_in | NOT IN (values) | string, number | {"field": "plan", "operator": "not_in", "value": ["free"]} |
contains | LIKE '%value%' | string | {"field": "email", "operator": "contains", "value": "@acme.com"} |
not_contains | NOT LIKE '%value%' | string | {"field": "email", "operator": "not_contains", "value": "test"} |
starts_with | LIKE 'value%' | string | {"field": "name", "operator": "starts_with", "value": "John"} |
ends_with | LIKE '%value' | string | {"field": "email", "operator": "ends_with", "value": "@acme.com"} |
greater_than | > value | number | {"field": "properties.order_count", "operator": "greater_than", "value": 5} |
less_than | < value | number | {"field": "properties.balance", "operator": "less_than", "value": 0} |
gte | >= value | number | {"field": "properties.age", "operator": "gte", "value": 18} |
lte | <= value | number | {"field": "properties.age", "operator": "lte", "value": 65} |
between | BETWEEN a AND b | number, date | {"field": "properties.age", "operator": "between", "value": [18, 65]} |
exists | IS NOT NULL | any | {"field": "phone", "operator": "exists"} |
not_exists | IS NULL | any | {"field": "properties.opted_out", "operator": "not_exists"} |
is_empty | = '' | string | {"field": "phone", "operator": "is_empty"} |
is_not_empty | != '' | string | {"field": "email", "operator": "is_not_empty"} |
date_before | < date | date | {"field": "created_at", "operator": "date_before", "value": "2026-01-01"} |
date_after | > date | date | {"field": "created_at", "operator": "date_after", "value": "2026-01-01"} |
date_in_last | > now - N days | date | {"field": "created_at", "operator": "date_in_last", "value": 30} |
has_executed | Join on events | event name | {"field": "event", "operator": "has_executed", "value": "purchase_completed"} |
has_not_executed | Left join IS NULL | event name | {"field": "event", "operator": "has_not_executed", "value": "onboarding_completed"} |
Accessing Nested Properties
Use dot notation to filter on contact properties:
Exclusion Rules
Exclusion rules remove contacts from the segment regardless of whether they match the inclusion filters. Each exclusion rule uses the same {field, operator, value} format.
Permissions
| Endpoint | Required Permission |
|---|---|
| List, Get, Evaluate, Estimate, Contacts, History, Usage | segments:read |
| Create, Update (PUT/PATCH), Delete, Archive, Unarchive, Duplicate | segments:write |