# Segments

Named audience segments — manual groups subscribers join by key from any framework, and auto segments computed from app activity — that sends and schedules can target.

A segment is a named group of **subscribers** (indie sub ids) that you can target in a send or a [schedule rule](/docs/scheduling). Two kinds:

| Kind       | Membership                                                                   | Example                                               |
| ---------- | ---------------------------------------------------------------------------- | ----------------------------------------------------- |
| **Manual** | Subscribers join and leave by a stable **key** from your app (any framework) | "Beta testers", "Sunday volunteers"                   |
| **Auto**   | Computed live from app-open activity                                         | "Lapsed (30 days)", "Active (7 days)", "New (7 days)" |

## Manual segments — join by key

Each manual segment has a **key** you choose at creation: 1–64 characters, lowercase letters, digits, dashes or underscores (start with a letter or digit). It is the contract your app code subscribes with, so it is **immutable after creation** — to change it, delete the segment and recreate it.

### From your app (any framework)

List what a client can subscribe to:

```text
GET https://app.nativenotify.com/api/segments/list/:appId/:appToken
```

```json
{
  "ok": true,
  "segments": [
    { "id": 41, "name": "Beta testers", "key": "beta-testers", "kind": "manual", "rule": null, "count": 128, "subscribable": true }
  ]
}
```

Join and leave (both idempotent — calling `subscribe` twice is fine):

```text
POST https://app.nativenotify.com/api/segments/subscribe
POST https://app.nativenotify.com/api/segments/unsubscribe
```

```json
{ "appId": 123, "appToken": "yourAppToken", "segmentKey": "beta-testers", "subscriberId": "user_8241" }
```

Subscribe answers `201` with `{ ok, joined, alreadyMember, subscriberId, count, segment }`; unsubscribe answers `200` with `{ ok, removed, wasMember, count, segment }`. `count` is the segment's live size after the change.

**Errors** use the standard envelope: `missing_field` (`segmentKey`/`subscriberId`), `app_not_found`, `404 segment_not_found` (unknown key), `400 auto_segment` (clients cannot join an auto segment by key).

### From the dashboard or the agent

The dashboard's **Segments** tab (Agent Notify) and the agent in chat manage the same objects: create a manual segment (name + optional key + description), rename, delete, add/remove individual subscribers, and see growth/opt-out counts from the recorded join/leave events. Agents have `get_audiences`, `create_segment`, `update_segment`, `delete_segment`, `add_segment_members` and `remove_segment_members` tools.

Deleting a segment that a schedule rule depends on answers `409` — never a silent cascade.

## Auto segments

Auto segments update themselves from the app-open data Native Notify already records (SDK registration/app opens, or indie registrations). Three rules ship today:

| Rule         | Membership                                                        |
| ------------ | ----------------------------------------------------------------- |
| `lapsed_30d` | Subscribers who have not opened the app in the last 30 days.      |
| `active_7d`  | Subscribers who opened the app in the last 7 days.                |
| `new_7d`     | Subscribers whose first recorded app open was in the last 7 days. |

One segment per rule per app. Auto segments reject manual member edits (and cannot be joined by key) — they are always exactly what the rule says.

## Sending to a segment

- **Recurring rules:** `audienceKind: "segment"` + `segmentId` — see [Scheduling](/docs/scheduling).
- **Sends:** the agent and dashboard can send to a segment by resolving it to its subscriber ids through the indie group path; the public [group push API](/docs/indie-push-notifications/api) takes `subIDs` directly if you prefer to resolve audience yourself.

## What a subscriber is

A subscriber is an **indie** identity: `subscriberId` on a [universal registration](/docs/universal-push/registration) or your sub id on the SDK path (`POST /api/indie/id`). One subscriber can be many devices — that is the supported pattern (a whole small group can share one sub id).
