Segments
Segments are dynamic contact groups defined by filter criteria. The contact list is computed at query time based on nested AND/OR filter logic — segments do not store a static list of contacts.
Naming note: Segments are referred to as "boards" in the API. All endpoint paths, request/response field names, and error messages use
board/boards. Use the/boardspaths when making API calls.
All endpoints require authentication via the X-API-Key header. See Authentication.
Visibility model
- Team segments (
isPrivate: false): Visible to all users in the organization. - Private segments (
isPrivate: true): Visible only to the segment owner. - Admins: Can see all segments, including other users' private segments.
Filter system
Segments define dynamic groups via nested AND/OR filter criteria:
Each criterion has a field, an operator, and a value. Criteria can be nested with additional AND/OR groups.
Supported operators
| Operator | Description | Value type |
|---|---|---|
equals | Exact match. | any |
not_equals | Not equal. | any |
contains | Case-insensitive substring match. | string |
not_contains | Case-insensitive substring exclusion. | string |
starts_with | Case-insensitive prefix match. | string |
ends_with | Case-insensitive suffix match. | string |
greater_than | Numeric greater than. | number |
less_than | Numeric less than. | number |
greater_than_or_equal | Numeric greater than or equal. | number |
less_than_or_equal | Numeric less than or equal. | number |
is_empty | Field is null, empty string, or empty array. | — |
is_not_empty | Field is not null, empty string, or empty array. | — |
any_of | At least one value matches. | string[] |
none_of | No values match. | string[] |
all_of | All values are present. | string[] |
date_equals | Matches a full day. | string or number |
date_not_equals | Excludes a full day. | string or number |
date_after | After end of day. | string or number |
date_before | Before start of day. | string or number |
date_after_or_equals | From start of day onward. | string or number |
date_before_or_equals | Through end of day. | string or number |
boolean | True or false/null/undefined. | boolean |
Create a segment
POST /boards
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | Yes | Must be unique per org. |
filters | object | Yes | Filter object with type (AND or OR) and criteria array. |
isPrivate | boolean | Yes | true for private (owner-only), false for team-visible. |
Example request
Response
Errors
| Status | Message | Cause |
|---|---|---|
| 400 | Invalid board name | Missing or empty name. |
| 400 | Board name is already taken | Duplicate name within the org. |
| 400 | Filters cannot be empty | Missing filters. |
| 400 | IsPrivate cannot be empty | Missing isPrivate field. |
List segments
GET /boards
Returns segments visible to the current user. Each segment includes a dynamically calculated count of matching contacts.
Query parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
filter | string | — | team (public + admin-visible private) or private (own private segments only). |
search | string | — | Case-insensitive search on segment name. |
page | number | 0 | 0-indexed. |
perPage | number | 50 | Items per page. |
Example request
Response
Get a segment
GET /boards/:id
Returns a single segment with its dynamically calculated contact count.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Segment ID. |
Example request
Response
Errors
| Status | Message | Cause |
|---|---|---|
| 404 | Board not found | No segment with that ID in your org. |
Get segment contacts
GET /boards/:id/contacts
Returns the contacts matching a segment's filters. Contacts are computed dynamically — only non-archived contacts are included.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Segment ID. |
Query parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
search | string | — | Case-insensitive search across firstName, lastName, email, phone. |
page | number | 0 | 0-indexed. |
perPage | number | 50 | Items per page. |
Example request
Response
Errors
| Status | Message | Cause |
|---|---|---|
| 404 | Board not found | No segment with that ID in your org. |
Update a segment
PUT /boards/:id
All fields are optional. Segment name must be unique per org if changed.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Segment ID. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | No | Must be unique per org. |
filters | object | No | New filter configuration. |
isPrivate | boolean | No | |
archived | boolean | No | Archive or unarchive. |
userId | string | No | Reassign segment owner. |
Example request
Response
Errors
| Status | Message | Cause |
|---|---|---|
| 400 | Board name is already taken | Duplicate name within the org. |
| 400 | Validation error | Invalid filters or field values. |
| 404 | Board not found | No segment with that ID in your org. |
Delete a segment
DELETE /boards/:id
Hard-deletes a segment. Returns the count of deleted records.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Segment ID. |
Example request
Response
Errors
| Status | Message | Cause |
|---|---|---|
| 400 | Invalid Board Id | Invalid ObjectId format or deletion failed. |
Response envelope
All endpoints use the standard envelope:
Error responses:
data is null for a general failure, such as a database error or an upstream timeout. When the request is rejected because of a specific field, data carries the field(s) at fault instead:
Each issue carries a path (the dotted path into the request body) and a message. A label is added when the path is not self-describing, which today means custom fields only, for example "path": "fields.68b0a1f39c2e4d0012ab77e5", "label": "Class Year". issues is an array, but treat it as holding at most one entry: validation stops at the first failure.