# Notify

`POST` `https://api.pushwoosh.com/messaging/v2/notify`

Creates and schedules a single message.

## Request structure

The request body is a `NotifyRequest` with exactly one of two kinds:

- [`segment`](#notifysegment): target an audience segment by segment code, a [seglang](/developer/api-reference/segmentation-filters-api/segmentation-language/) expression, or a structured filter expression.
- [`transactional`](#notifytransactional): send to an explicit list of hwids, user IDs, push tokens, or test devices.

```json title="Shape"
{
  "segment": { ... },      // OR
  "transactional": { ... },
  "transaction_id": "unique-uuid"
}
```

| Field | Type | Description |
|---|---|---|
| `transaction_id` | string | Optional. Idempotency key for the request — works with both `segment` and `transactional`. A repeat call with the same `transaction_id` within 5 minutes returns the original `message_code` instead of sending a duplicate message. Use a UUID or another value unique per logical send. |

<Aside type="caution" title="Only the key is checked, not the payload">
Deduplication matches on `transaction_id` alone. If a retry reuses the same `transaction_id` but sends a different `segment` / `transactional` body, the original `message_code` is still returned and the new body is silently discarded — it is not compared against the first request. Never reuse a `transaction_id` across logically different messages.
</Aside>

<Aside type="tip">
This is the same deduplication mechanism as `transactionId` on the legacy [Messages API](/developer/api-reference/messages-api/), sharing the same 5-minute storage window, so a retried request is deduplicated across `/createMessage` and `Notify` alike. It is unrelated to the `transaction_id` attribute on [`PW_Conversion`](/product/audience-data-and-segmentation/events/conversion-events/#attributes-for-the-postevent-call) revenue events, which Pushwoosh stores as-is and does not use for deduplication.
</Aside>

## NotifySegment

Targets users who match an audience segment or filter expression.

| Field | Type | Description |
|---|---|---|
| `schedule` | [`Schedule`](#schedule) | When and how to send. Required. |
| `application` | string | [Application code](/developer/api-reference/api-identifiers/#application-code). |
| `platforms` | array of [`Platform`](#platform-enum) | Platforms the message targets. |
| `code` | string | [Segment code](/developer/api-reference/api-identifiers/#segment--filter-code). Mutually exclusive with `expression` and `filter_expression`. |
| `expression` | string | [Seglang](/developer/api-reference/segmentation-filters-api/segmentation-language/) expression. |
| `filter_expression` | `FilterExpression` | Structured filter expression (advanced). |
| `payload` | [`Payload`](/developer/api-reference/messaging-api-v2/payload-reference/) | Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber payload. Mutually exclusive with `email_payload`. |
| `email_payload` | [`EmailPayload`](/developer/api-reference/messaging-api-v2/email-payload-reference/) | Email payload. |
| `campaign` | string | [Campaign code](/developer/api-reference/api-identifiers/#campaign-code) to attribute this message to. |
| `frequency_capping` | [`FrequencyCapping`](#frequencycapping) | Per-user frequency limits. |
| `send_rate` | [`SendRate`](#sendrate) | Throttling for the send. |
| `message_type` | [`MessageType`](#messagetype-enum) | `MESSAGE_TYPE_MARKETING` (default) or `MESSAGE_TYPE_TRANSACTIONAL`. Controls control-group filtering. |
| `dynamic_content_placeholders` | map&lt;string, string&gt; | Replaces placeholders in content. |
| `meta_data` | object | Free-form metadata forwarded to downstream analytics. |

### Example: Send to a segment

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "segment": {
      "application": "XXXXX-XXXXX",
      "platforms": ["IOS", "ANDROID"],
      "code": "active_users",
      "payload": {
        "content": {
          "localized_content": {
            "en": {
              "ios":     { "body": "Hello!" },
              "android": { "body": "Hello!" }
            }
          }
        }
      },
      "schedule": { "at": "2026-05-01T12:00:00Z" },
      "message_type": "MESSAGE_TYPE_MARKETING"
    }
  }'
```

## NotifyTransactional

Sends to an explicit list of recipients.

| Field | Type | Description |
|---|---|---|
| `schedule` | [`Schedule`](#schedule) | Required. |
| `application` | string | [Application code](/developer/api-reference/api-identifiers/#application-code). |
| `platforms` | array of [`Platform`](#platform-enum) | Platforms the message targets. |
| `test_devices` | bool | If `true`, send to the app's test devices only. |
| `hwids` | `{ "list": [string, ...] }` | Send to these [hwids](/developer/pushwoosh-knowledge-hub/device-identifiers/#hwid) only. |
| `users` | `{ "list": [string, ...] }` | Send to these [user IDs](/developer/pushwoosh-knowledge-hub/users-userids/) only. |
| `push_tokens` | `{ "list": [string, ...] }` | Send to these [push tokens](/developer/pushwoosh-knowledge-hub/device-identifiers/#push-token) only. |
| `payload` | [`Payload`](/developer/api-reference/messaging-api-v2/payload-reference/) | Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber payload. |
| `email_payload` | [`EmailPayload`](/developer/api-reference/messaging-api-v2/email-payload-reference/) | Email payload. |
| `return_unknown_identifiers` | bool | When `true`, the response's `unknown_identifiers` lists identifiers that were not found. |
| `use_latest_user_device` | bool | Only applies when you target `users`. When `true`, the message is delivered to each user's most recently active device — the one with the latest Last Application Open — instead of all devices tied to that user ID. Defaults to `false` (send to every device). |
| `campaign`, `frequency_capping`, `send_rate`, `message_type`, `dynamic_content_placeholders`, `meta_data` | | See `NotifySegment` above. |

`test_devices`, `hwids`, `users`, and `push_tokens` are mutually exclusive. Exactly one must be set.

### Example: Transactional by user IDs

```bash
curl -X POST https://api.pushwoosh.com/messaging/v2/notify \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transactional": {
      "application": "XXXXX-XXXXX",
      "platforms": ["IOS", "ANDROID"],
      "users": { "list": ["user-123", "user-456"] },
      "payload": {
        "content": {
          "localized_content": {
            "en": { "ios": { "body": "Your order has shipped." } }
          }
        }
      },
      "schedule": { "at": "2026-05-01T12:00:00Z" },
      "message_type": "MESSAGE_TYPE_TRANSACTIONAL",
      "return_unknown_identifiers": true,
      "use_latest_user_device": true
    }
  }'
```

## Response

```json
{
  "result": {
    "message_code": "XXXXX-XXXXX-XXXXX",
    "unknown_identifiers": []
  }
}
```

| Field | Type | Description |
|---|---|---|
| `message_code` | string | Unique [message code](/developer/api-reference/api-identifiers/#message-code). Use it with [`/getMessageDetails`](/developer/api-reference/messages-api/#getmessagedetails) and message statistics endpoints. |
| `unknown_identifiers` | array of string | Identifiers not found on the account. Populated only when `return_unknown_identifiers: true` was set on the `transactional` kind. |

## Shared types

### Schedule

```json
{
  "at": "2026-05-01T12:00:00Z",
  "follow_user_timezone": true,
  "past_timezones_behaviour": "PAST_TIMEZONES_BEHAVIOUR_SEND_IMMEDIATELY"
}
```

| Field | Type | Description |
|---|---|---|
| `at` | timestamp | Absolute send time (RFC 3339). If in the past, the message is sent immediately. Maximum 14 days in the future. |
| `after` | duration | Alternative to `at`. Send after this offset from "now" (e.g. `"3600s"`). |
| `follow_user_timezone` | bool | When `true`, each device receives the message at `at` in its local timezone. |
| `past_timezones_behaviour` | enum | `PAST_TIMEZONES_BEHAVIOUR_SEND_IMMEDIATELY` (default), `PAST_TIMEZONES_BEHAVIOUR_DO_NOT_SEND`, or `PAST_TIMEZONES_BEHAVIOUR_NEXT_DAY`. Only meaningful when `follow_user_timezone` is `true`. |

### FrequencyCapping

Per-user frequency limits for marketing sends. To disable capping, omit `frequency_capping` entirely, or send `days: 0` together with `count: 0`.

```json
{ "days": 7, "count": 3, "exclude": false, "avoid": true }
```

- `days` (int, 1–30, or `0` to disable capping): look-back window. Must be sent together with `count` — if one is `0`, the other must also be `0`; sending one as `0` while the other is nonzero returns `400`.
- `count` (int, 1 or higher, or `0` to disable capping): maximum messages allowed within `days`. Same pairing rule as `days` above.
- `exclude` (bool): hard-exclude users who have already hit the cap.
- `avoid` (bool): soft-avoid users who have already hit the cap (they still count toward analytics).

<Aside type="caution" title="Important">
Sending `days` and `count` with mismatched zero-ness (e.g. `{"days": 0, "count": 5}`) returns `400`. This validation is a breaking change to `Notify` — clients that previously relied on a lone `0` being silently ignored will now get an error instead.
</Aside>

### SendRate

```json
{ "value": 500, "bucket": "1s", "avoid": false }
```

Throttles the send. `value` is messages per `bucket`; typical `bucket` is `"1s"`.

### Platform enum

`IOS`, `ANDROID`, `OSX`, `WINDOWS`, `AMAZON`, `SAFARI`, `CHROME`, `FIREFOX`, `IE`, `EMAIL`, `BAIDU_ANDROID`, `HUAWEI_ANDROID`, `SMS`, `WEB`, `KAKAO`, `TELEGRAM`, `LINE`, `WHATS_APP`, `VIBER`.

### MessageType enum

- `MESSAGE_TYPE_UNSPECIFIED`: equivalent to `MESSAGE_TYPE_MARKETING`.
- `MESSAGE_TYPE_MARKETING`: subject to control-group filtering and frequency capping.
- `MESSAGE_TYPE_TRANSACTIONAL`: skips control-group filtering and frequency capping. Use for order confirmations, OTPs, and similar critical flows.

## Related

<CardGrid>
  <LinkCard title="Cancel" href="/developer/api-reference/messaging-api-v2/cancel/" />
  <LinkCard title="Payload reference" href="/developer/api-reference/messaging-api-v2/payload-reference/" />
  <LinkCard title="Email payload reference" href="/developer/api-reference/messaging-api-v2/email-payload-reference/" />
  <LinkCard title="Migration from v1" href="/developer/api-reference/messaging-api-v2/migration-from-v1/" />
</CardGrid>