Preview a segment

POST/api/v1/segments/preview
Requires anorganization API keywith the scopecontacts:read

How many contacts a set of rules currently matches, and a sample of them, without saving the segment. Call this before sending to one.

Rules take one of four kinds of field:

Kind Fields Example
Contact columns email, name, status {"field": "email", "op": "ends_with", "value": "@acme.com"}
Custom fields any key from GET /contact-fields {"field": "plan", "op": "equals", "value": "pro"}
Engagement opened, clicked, emailed {"field": "opened", "op": "within_days", "value": "90"}
Membership tag, interest {"field": "tag", "op": "equals", "value": "vip"}

tag matches by NAME, interest matches by ID. That asymmetry is deliberate. A tag is written by name everywhere — created on first use, case-insensitively — so a rule holding a ULID would break the moment somebody renamed it. An interest is an answer to a question the contact was asked and its name is form copy, so rewording "Product updates" must not silently empty every segment built on it.

Membership fields take equals, not_equals, is_set (has any) and is_not_set (has none). Deliberately not contains: a tag is on a contact or it is not, and a substring match over a set would let contains "vip" quietly also match vip-churn-risk.

not_equals means "does not carry it", not "carries something else". A contact with both vip and churn-risk is EXCLUDED by tag is not vip — they carry it. A contact with no tags at all is included, because they do not.

A rule we cannot evaluate — an unparseable number or date, a blank tag — matches nothing. Widening is the dangerous direction: it mails people who were never meant to be in the audience, and it does so quietly.

Request

POST/api/v1/segments/preview
curl -X POST 'https://app.mailyte.com/api/v1/segments/preview' \
  -H 'Authorization: Bearer mk_live_YOUR_API_KEY'
The key names its own organization, so no X-Organization-ID header is needed.

Response

Success.

  • dataobject
    • objectstringsegment_preview
    • countinteger

      Every contact the rules match — exact, and NOT the size of `sample`.

    • samplearray<object>

      At most five matches, in the query's own order, so an author can see the audience is the one they meant. It is a sample, not a page: there is no pagination and no promise about which five. Rows are not contact objects and carry no id — the preview query selects only these three columns; save the segment if you want the matching contacts.

      • emailstring
      • namestring

        The contact's display name, read from the same column `contact.name` publishes. `null` means NONE — this contact has no name recorded — never "the preview left it out": `name` is one of the three columns the preview query selects, so it is always a real answer.

      • statestringsubscribed | unsubscribed | bounced | complained | suppressed

        Literally `contact.state`, resolved by the same code against the same suppression list, so a preview can never disagree with the contact endpoint about who is mailable.

Returned inside the standard envelope.

Errors

StatusWhen
401The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist.
403The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys.
404No such resource in this organization.
422The request was understood but the values were not acceptable.
429Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait.

Every status, with what causes it and what to do, is on the error reference.