Segments
Create and manage audience segments with dynamic filter criteria for targeted campaigns
Segments let you group contacts by shared characteristics using filter rules. Dynamic segments automatically recalculate membership as contact data changes.
Authentication
Requires an API key with the contacts scope, or an active session.
Authorization: Bearer msk_...
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/segments | List segments |
POST | /v1/segments | Create segment |
GET | /v1/segments/:id | Get segment |
PATCH | /v1/segments/:id | Update segment |
DELETE | /v1/segments/:id | Delete segment |
GET | /v1/segments/:id/preview | Preview matching contacts |
POST | /v1/segments/:id/refresh | Recalculate membership |
Filter criteria
Each segment uses a filter_criteria object with a top-level operator and an array of rules.
{
"operator": "AND",
"rules": [
{
"field": "status",
"operator": "equals",
"value": "subscribed"
},
{
"field": "created_at",
"operator": "after",
"value": "2026-01-01"
},
{
"field": "tags",
"operator": "contains",
"value": "early-adopter"
}
]
}Supported operators per field:
| Operator | Description |
|---|---|
equals / not_equals | Exact match |
contains / not_contains | Substring or array membership |
starts_with / ends_with | String prefix/suffix |
greater_than / less_than | Numeric or date comparison |
before / after | Date comparison |
is_empty / is_not_empty | Null/blank check |
in / not_in | Match against a list of values |
List segments
GET /v1/segments
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 20 | Results per page (max 100) |
curl https://api.misar.io/mail/v1/segments \
-H "Authorization: Bearer msk_..."const res = await fetch("https://api.misar.io/mail/v1/segments?page=1&limit=20", {
headers: { Authorization: "Bearer msk_..." },
});
const { data } = await res.json();Response
{
"success": true,
"data": {
"segments": [
{
"id": "seg_01hvxyz",
"name": "Active subscribers — Q1 2026",
"description": "Subscribed after Jan 1 with early-adopter tag",
"segment_type": "dynamic",
"contact_count": 1842,
"last_calculated_at": "2026-05-27T10:00:00Z",
"created_at": "2026-03-15T08:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 7,
"total_pages": 1
}
}
}Create a segment
POST /v1/segments
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | 1–200 characters |
description | string | No | Max 1000 characters |
segment_type | dynamic | static | Yes | Dynamic re-evaluates on refresh; static is manually managed |
filter_criteria | object | Yes | { operator, rules } |
curl -X POST https://api.misar.io/mail/v1/segments \
-H "Authorization: Bearer msk_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Active subscribers — Q1 2026",
"description": "Subscribed after Jan 1 with early-adopter tag",
"segment_type": "dynamic",
"filter_criteria": {
"operator": "AND",
"rules": [
{ "field": "status", "operator": "equals", "value": "subscribed" },
{ "field": "created_at", "operator": "after", "value": "2026-01-01" },
{ "field": "tags", "operator": "contains", "value": "early-adopter" }
]
}
}'const res = await fetch("https://api.misar.io/mail/v1/segments", {
method: "POST",
headers: {
Authorization: "Bearer msk_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Active subscribers — Q1 2026",
segment_type: "dynamic",
filter_criteria: {
operator: "AND",
rules: [
{ field: "status", operator: "equals", value: "subscribed" },
{ field: "created_at", operator: "after", value: "2026-01-01" },
{ field: "tags", operator: "contains", value: "early-adopter" },
],
},
}),
});
const { data } = await res.json();Response
The segment is evaluated immediately on creation. contact_count and last_calculated_at are populated in the response.
{
"success": true,
"data": {
"id": "seg_01hvxyz",
"name": "Active subscribers — Q1 2026",
"segment_type": "dynamic",
"filter_criteria": {
"operator": "AND",
"rules": [...]
},
"contact_count": 1842,
"last_calculated_at": "2026-05-27T10:01:44Z",
"created_at": "2026-05-27T10:01:44Z",
"updated_at": "2026-05-27T10:01:44Z"
}
}Get a segment
GET /v1/segments/:id
Returns the full segment object including filter_criteria and current contact_count.
Update a segment
PATCH /v1/segments/:id
Send only the fields to change. Updating filter_criteria triggers an immediate re-evaluation.
Delete a segment
DELETE /v1/segments/:id
Returns { "success": true }. Deleting a segment does not delete the contacts in it.
Preview segment contacts
GET /v1/segments/:id/preview
Returns a sample of contacts that currently match the segment criteria without persisting any changes.
{
"success": true,
"data": {
"contacts": [...],
"total_matching": 1842
}
}Refresh a segment
POST /v1/segments/:id/refresh
Recalculates dynamic segment membership against the latest contact data. Returns the updated contact_count.
{
"success": true,
"data": {
"contact_count": 1901,
"last_calculated_at": "2026-05-27T11:00:00Z"
}
}Dynamic segments refresh automatically on a schedule. Use the refresh endpoint to force an immediate recalculation before sending a campaign.