Misar IO Docs
MisarMailApi Reference

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

MethodPathDescription
GET/v1/segmentsList segments
POST/v1/segmentsCreate segment
GET/v1/segments/:idGet segment
PATCH/v1/segments/:idUpdate segment
DELETE/v1/segments/:idDelete segment
GET/v1/segments/:id/previewPreview matching contacts
POST/v1/segments/:id/refreshRecalculate 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:

OperatorDescription
equals / not_equalsExact match
contains / not_containsSubstring or array membership
starts_with / ends_withString prefix/suffix
greater_than / less_thanNumeric or date comparison
before / afterDate comparison
is_empty / is_not_emptyNull/blank check
in / not_inMatch against a list of values

List segments

GET /v1/segments

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Results 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

FieldTypeRequiredDescription
namestringYes1–200 characters
descriptionstringNoMax 1000 characters
segment_typedynamic | staticYesDynamic re-evaluates on refresh; static is manually managed
filter_criteriaobjectYes{ 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.