> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymorfa.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Save an audience segment

> Select customer-supplied audience profiles with saved rules and freeze the matches when a campaign launches.

A segment is a named set of rules over your team's [audience profiles](/guides/campaigns/audience-profiles).
It selects profiles you supplied, using tags, attributes, consent assertions and
recorded outcomes of your team's campaigns. WhatsApp contacts, chats and message
content are never a source for segments.

> [!NOTE]
>
> Audience segments require access to both the audience profiles and audience
> segments betas. Until both are offered to and joined by your team, new segments,
> edits, previews and segment campaign launches are refused. Reading and deleting
> saved segments remain available after withdrawal. Withdrawal pauses running
> segment campaigns before their next dispatch pass; messages already sent cannot
> be recalled.

Use a team API key. Reads require `campaigns:read`; writes and unsaved-rule
previews require `campaigns:manage`. Project and client tokens cannot access
these team resources. Your team can save at most 100 segments.

## Use segments in the Console

Open **Campaigns > Segments** to list, create, edit and delete segments.

1. Select **New segment**, enter a name and add conditions. Each group shows
   whether it matches all or any of its conditions. Select **Exclude matches**
   to negate a group. **Profiles must match** combines the groups.
2. The **Live count** panel recounts a short pause after each valid edit. It
   shows eligible, matching, opted-out and consent-withheld profiles, with up
   to five masked sample numbers. The count is an estimate; launch counts again.
3. Select **Create segment** or **Save changes**. If someone else saved the
   segment first, your edits stay on screen. Choose **Keep my edits** to save
   over the newer revision, or **Load saved version** to discard them.

To send to a segment, choose **Saved segment** in the campaign builder's
audience step. The review step shows a fresh count. After launch, the campaign
page shows the revision, time and number of profiles that launch froze,
separately from a live count of current matches.

Without both betas, the Console shows segments as view and delete only.

If counting the segment takes too long at launch, nothing is sent and the
Console offers **Retry**. Simplify the rules if it happens again. A campaign
whose segment was deleted cannot be duplicated; create a new campaign and
choose an audience instead.

## Save and preview rules with the API

```bash theme={null}
curl -X POST "https://api.polymorfa.com/platform/audience-segments" \
  -H "Authorization: Bearer $POLYMORFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "VIP buyers",
    "rules": {
      "match": "all",
      "groups": [{
        "match": "all",
        "negate": false,
        "conditions": [
          { "field": "tag", "operator": "contains", "value": "vip" },
          { "field": "attribute", "name": "orders", "operator": "greater_than", "value": 2 }
        ]
      }]
    }
  }'
```

The response's `data` contains `id`, `name`, `revision`, `rules`, `createdAt`
and `updatedAt`. Times are Unix milliseconds. Use the returned ID with
`GET /platform/audience-segments/{segmentId}/preview` for a live count. To test
rules before saving, send `{ "rules": ... }` to
`POST /platform/audience-segments/preview`.

Each preview returns `matchedCount`, `optedOutCount`, `consentWithheldCount`,
`eligibleCount`, `evaluatedAt` and `sample`. The sample contains at most five
eligible profiles, each with a masked `phone` and its `tags`. A saved preview
also returns the evaluated `revision`. Counts describe that evaluation, not a
reservation of recipients. Opted-out profiles count under `optedOutCount`;
`consentWithheldCount` counts only matching profiles that are not opted out and
whose latest campaign consent assertion is false. No assertion is distinct from
a false assertion.

## Rule meanings and limits

The root combines groups with `match: "all"` or `"any"`. Each group combines
conditions the same way. `negate: true` inverts the whole group's result and
defaults to false. There are no nested groups beyond these two levels.

| Field | Operators and values |
| - | - |
| `tag` | `contains` with `value`, `in` with `values`, or `exists` for any tag. Tags compare exactly. |
| `attribute` | Set `name`. Use `equals` with a string, number or boolean; `in` with strings or numbers; `contains` with text; `greater_than` or `less_than` with a number; `before` or `after` with a date; or `exists`. |
| `consent` | `equals` with boolean `value`, compared with the latest campaign consent assertion. |
| `campaign` | Set `campaignId` and `outcome`: `delivered`, `not_delivered`, `read`, `not_read`, `replied`, `not_replied` or `failed`. Uses the same definitions as [retargeting audiences](/guides/campaigns/audiences). |

Attribute equality preserves types: number `9` differs from string `"9"`.
`contains` on text ignores case and matches literal substrings. Missing or null
attributes and values of another type do not match, before group negation.
Thus a negated city-equals rule also includes profiles with no city.
Dates use `YYYY-MM-DD` at midnight UTC, or a date-time with `Z` or an explicit
offset. `before` and `after` are exclusive. Relative dates are unsupported.

Rules allow 1 to 10 groups, 1 to 20 conditions per group, at most 40 conditions
in total and 5 campaign conditions. An `in` condition accepts 1 to 50 distinct
values. Normalized rules are limited to 16 KiB of compact UTF-8 JSON.
Tag values allow 1-48 UTF-8 bytes; text attribute values allow 1-256 UTF-8
bytes. Multibyte characters reach these limits with fewer characters.
Names are trimmed and use 1 to 100 characters
without control characters. Unknown fields and unsupported operators return `400`.
A campaign condition must name a campaign in your team.

## Launch a campaign from a segment

Set `segmentId` when creating or updating a campaign. A request cannot set both
`segmentId` and `recipientListId`. Choosing a segment clears a linked list;
choosing a list clears the segment. Only an unlaunched draft can change its
audience. Set `segmentId: null` in an update to clear it.

Launch evaluates the saved rules once and freezes the matching profiles and
their non-null attributes as recipient variables. Inline recipients already on
the campaign keep their own variables. Profiles with a latest false campaign
consent assertion are excluded. Opted-out recipients are skipped, and live
suppression still applies during sending. A segment never grants permission to send.

The campaign returns `segmentId` and `segmentSnapshot`. Before launch the snapshot
is null; afterward it contains `revision`, `evaluatedAt` and `matchedCount`.
A scheduled campaign freezes recipients when you launch it, before its scheduled
start. Later profile or segment edits do not rewrite that snapshot. Duplicating
a campaign with a linked segment evaluates the segment again at the copy's launch.

## Edit or delete a segment

List saved segments with `GET /platform/audience-segments?limit=25`. Follow
`page.nextCursor` until `page.hasMore` is false. The limit is 1 to 100.
Read one with `GET /platform/audience-segments/{segmentId}`.

Send `PATCH /platform/audience-segments/{segmentId}` with `expectedRevision` and
`name`, `rules`, or both. A successful update increments the revision. A stale
revision returns `409`; reread before applying your intended edit.

Delete with `DELETE /platform/audience-segments/{segmentId}?expectedRevision=2`.
`expectedRevision` is a positive integer for both update and delete.
Deletion returns `{ "data": { "deleted": true, "id": "..." } }`. It returns
`409` while an unlaunched draft uses the segment. Choose another audience for
those drafts first. Launched campaigns keep their recipients and snapshot, and
their `segmentId` becomes null. Deleting a profile removes it from future
segment evaluations, while already frozen campaign recipients retain the
[profile deletion behavior](/guides/campaigns/audience-profiles#delete-and-recreate-a-profile).

Invalid inputs return `400`, denied access returns `403`, missing or foreign
segments return `404`, and stale revisions, capacity limits, in-use deletion
or evaluation timeouts return `409`. This includes evaluation during campaign
launch: no recipients or launch are committed. Simplify the rules and retry
after an evaluation timeout.
See the [segment API reference](/api-reference/platform/audience-segments/create-audience-segment).

## Duplicate and launch a segment campaign

Use a team API key or a signed-in dashboard session to duplicate or launch a
segment campaign. Project tokens are refused with 403, even when they have
`campaigns:manage`. Both audience betas must remain available; otherwise a new
copy or launch returns 403 `feature_unavailable`.

A duplicate keeps the saved segment and evaluates it again at launch. It does
not copy the original campaign's frozen recipients. If that segment was deleted,
duplication returns 409 `state_conflict`. Create a new campaign and choose its
audience instead. An audience change during duplication or launch also returns
409; reload the campaign before trying again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.