Segments API — Mimeo docs

Segments API

Full parity with the UI. Segments are addressed by key, not by database id, so a definitions file can name one without knowing anything about your database.

Every endpoint needs a bearer token from Settings → Agents & API.

Endpoints

Method Path What it does
GET /api/v1/segments Every segment with its live count
POST /api/v1/segments Create one
GET /api/v1/segments/:key One segment, with rules and where it's used
PATCH /api/v1/segments/:key Update it
DELETE /api/v1/segments/:key Delete it
GET /api/v1/segments/:key/count Just the number
GET /api/v1/segments/:key/members The people, paginated
POST /api/v1/segments/preview Check and count rules without saving them

Count and members are separate on purpose. Asking "how many?" shouldn't make you pay for the list, and asking for the list shouldn't hand you forty thousand rows in one response. members is paginated, capped at 500 per page.

Creating a segment

curl -X POST https://your-mimeo.com/api/v1/segments \
  -H "Authorization: Bearer $MIMEO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{\n    "name": "Engaged customers",\n    "description": "Bought something and opened recent mail.",\n    "rules": {\n      "type": "all",\n      "conditions": [\
        { "type": "total_spend", "op": "greater", "value": 0 },\
        { "type": "opened_email", "email_id": 12, "within_days": 60 },\
        { "type": "not", "condition": { "type": "suppressed" } }\
      ]\n    }\n  }'```

The key is derived from the name (`engaged_customers`) unless you supply one.

## Checking rules before you commit to them

`preview` validates and counts a rule set without creating anything — the API's answer to the editor's live count, and what a definitions-repo diff should call before applying a change.

curl -X POST https://your-mimeo.com/api/v1/segments/preview
-H "Authorization: Bearer $MIMEO_TOKEN"
-H "Content-Type: application/json"
-d '{ "rules": { "type": "has_tag", "tag": "customer" } }'```

{
  "count": 412,
  "total": 5310,
  "exact": true,
  "expensive": false,
  "validation": { "valid": true, "errors": [], "warnings": [] }
}

Errors name the fix

Invalid rules come back as 422 with messages written to be acted on rather than just reported:

{
  "errors": [\
    "This rule tests field \"plan_tier\", which is not a defined field. Create it under People → Fields first."\
  ],
  "validation": { "valid": false, "errors": [ … ] }
}

Deleting a segment something still references is refused, with used_by listing what would break.

The rule vocabulary

The same condition types flows and guards use — see the schema reference for the full list. Segments add total_spend, and support within_days on received_email, opened_email and clicked_email.

email compares the person's email address, ignoring case, with equals, starts_with, ends_with or contains — so "everyone at acme.com" is { "type": "email", "op": "ends_with", "value": "@acme.com" }.

in_segment takes a segment key. A reference loop is rejected on save.

subscribed_on compares the date a person joined the list against a value like "2026-06-01", using less (before), greater (after) or equals (on). Both comparisons are strict. Everyone has the date, so this is a single condition with no null case to wrap:

{ "type": "all", "conditions": [\
    { "type": "subscribed_on", "op": "less", "value": "2026-06-01" },\
    { "type": "not", "condition": { "type": "suppressed" } }\
  ] }

Next: The subscription API →