# Notify

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

Cria e agenda uma única mensagem.

<span id="request-structure" />

## Estrutura da requisição

O corpo da requisição é um `NotifyRequest` com exatamente um de dois tipos:

- [`segment`](#notifysegment): direciona um segmento de público por código de segmento, ou — sem criar um segmento primeiro — uma expressão [seglang](/pt/developer/api-reference/segmentation-filters-api/segmentation-language/) ou uma expressão de filtro estruturada.
- [`transactional`](#notifytransactional): envia para uma lista explícita de hwids, IDs de usuário, tokens de push ou dispositivos de teste.

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

| Campo | Tipo | Descrição |
|---|---|---|
| `transaction_id` | string | Opcional. Chave de idempotência para a requisição — funciona tanto com `segment` quanto com `transactional`. Uma chamada repetida com o mesmo `transaction_id` dentro de 5 minutos retorna o `message_code` original em vez de enviar uma mensagem duplicada. Use um UUID ou outro valor único por envio lógico. |

<Aside type="tip">
Passe um cabeçalho `X-Request-ID` para correlacionar a mensagem criada com sua requisição para rastreamento de ponta a ponta — veja [ID da Requisição](/pt/developer/api-reference/api-identifiers/#request-id).
</Aside>

<Aside type="caution" title="Apenas a chave é verificada, não o payload">
A desduplicação corresponde apenas ao `transaction_id`. Se uma nova tentativa reutilizar o mesmo `transaction_id` mas enviar um corpo `segment` / `transactional` diferente, o `message_code` original ainda será retornado e o novo corpo será descartado silenciosamente — ele não é comparado com a primeira requisição. Nunca reutilize um `transaction_id` em mensagens logicamente diferentes.
</Aside>

<Aside type="tip">
Este é o mesmo mecanismo de desduplicação que o `transactionId` na [API de Mensagens](/pt/developer/api-reference/messages-api/) legada, compartilhando a mesma janela de armazenamento de 5 minutos, então uma requisição repetida é desduplicada tanto em `/createMessage` quanto em `Notify`. Não está relacionado ao atributo `transaction_id` em eventos de receita [`PW_Conversion`](/pt/product/audience-data-and-segmentation/events/conversion-events/#attributes-for-the-postevent-call), que o Pushwoosh armazena como está e não usa para desduplicação.
</Aside>

## NotifySegment

Direciona usuários que correspondem a um segmento de público ou expressão de filtro. Defina exatamente um entre `code`, `expression` ou `filter_expression`. Para `expression` e `filter_expression`, nenhum segmento precisa ser criado previamente — a expressão é avaliada inline apenas para este envio.

<Aside type="note" title="Escolhendo entre código e expressões inline">
Apenas um segmento salvo referenciado por `code` pode usar a pré-compilação de [entrega de alta velocidade](/pt/product/resources/high-speed-delivery/). `expression` e `filter_expression` são avaliados no momento do envio e nunca são pré-compilados.
</Aside>

| Campo | Tipo | Descrição |
|---|---|---|
| `schedule` | [`Schedule`](#schedule) | Quando e como enviar. Obrigatório. |
| `application` | string | [Código do Aplicativo](/pt/developer/api-reference/api-identifiers/#application-code). |
| `platforms` | array of [`Platform`](#platform-enum) | Plataformas que a mensagem direciona. |
| `code` | string | [Código do Segmento](/pt/developer/api-reference/api-identifiers/#segment--filter-code) de um segmento salvo antecipadamente. Mutuamente exclusivo com `expression` e `filter_expression`. |
| `expression` | string | Expressão [Seglang](/pt/developer/api-reference/segmentation-filters-api/segmentation-language/), avaliada apenas para este envio — nenhum segmento salvo é necessário. Mutuamente exclusivo com `code` e `filter_expression`. |
| `filter_expression` | `FilterExpression` | A mesma lógica que `expression`, como um objeto estruturado em vez de uma string seglang. Mutuamente exclusivo com `code` e `expression`. O esquema `FilterExpression` não está documentado publicamente — solicite-o ao suporte da Pushwoosh se precisar do formato estruturado. |
| `payload` | [`Payload`](/pt/developer/api-reference/messaging-api-v2/payload-reference/) | Payload de Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber / Facebook Messenger. Mutuamente exclusivo com `email_payload`. |
| `email_payload` | [`EmailPayload`](/pt/developer/api-reference/messaging-api-v2/email-payload-reference/) | Payload de e-mail. |
| `campaign` | string | [Código da Campanha](/pt/developer/api-reference/api-identifiers/#campaign-code) para atribuir esta mensagem. |
| `campaign_name` | string | Nome interno desta mensagem, exibido como o título da linha no Message History e em sua exportação. Sem relação com `campaign` acima. Não agrupa mensagens nem afeta a entrega. Máximo de 255 caracteres, cortado. Omita-o ou deixe-o vazio para que o título da linha venha do próprio conteúdo do payload. |
| `frequency_capping` | [`FrequencyCapping`](#frequencycapping) | Limites de frequência por usuário. |
| `send_rate` | [`SendRate`](#sendrate) | Controle de velocidade para o envio. |
| `message_type` | [`MessageType`](#messagetype-enum) | `MESSAGE_TYPE_MARKETING` (padrão) ou `MESSAGE_TYPE_TRANSACTIONAL`. Controla a filtragem do grupo de controle. |
| `dynamic_content_placeholders` | map&lt;string, string&gt; | Substitui placeholders no conteúdo. |
| `meta_data` | object | Metadados de formato livre encaminhados para análises downstream. |
| `use_latest_user_device` | bool | Quando `true`, entrega a mensagem para o dispositivo mais recentemente ativo de cada usuário (aquele com a última Abertura de Aplicativo) em vez de para todos os dispositivos correspondidos pelo segmento. Escopo para `platforms`: apenas dispositivos nessas plataformas são considerados, e se nenhum tiver dados de Última Abertura de Aplicativo, o primeiro dispositivo correspondente é usado em vez de descartar o envio. O padrão é `false` (enviar para todos os dispositivos). |
| `control_group` | string | Código ou nome de um grupo de retenção próprio do envio, a ser aplicado a esta mensagem. Ele não restringe quais [grupos de controle](/pt/product/audience-data-and-segmentation/control-groups/) se aplicam: todo grupo de controle ativo do aplicativo retém usuários dos envios de marketing, com este campo definido ou não. Mutuamente exclusivo com `holdout_percentage`. |
| `holdout_percentage` | uint32 | Separa esta parcela do segmento, de `1` a `20`, em um grupo de controle restrito a este envio, além dos grupos de controle ativos do aplicativo, para medir o impacto de uma única campanha sem consumir os grupos compartilhados. `0` (padrão) o mantém desativado. Mutuamente exclusivo com `control_group`. |

<Aside type="caution" title="Importante">
O Pushwoosh nomeia o grupo de retenção como `__holdout_<campaign code>` (ou `__holdout_<message code>` para um envio sem `campaign`) e reutiliza esse mesmo grupo, com sua porcentagem original, em todo envio posterior que compartilhe o código. A seleção é fixada na primeira vez que o grupo é criado. Esse grupo nunca aparece em **Configurações > Grupos de controle**, e redimensioná-lo, reembaralhá-lo, desativá-lo ou excluí-lo retorna `FailedPrecondition`, porque alterá-lo no meio da medição invalidaria a comparação.
</Aside>

Os dispositivos selecionados para o grupo de retenção são excluídos da entrega da mesma forma que pelos [grupos de controle](/pt/product/audience-data-and-segmentation/control-groups/#how-the-control-group-affects-message-delivery) do aplicativo. Nada é enviado a eles, e o log de rastreamento registra o descarte como `Device is in control group`. Um `message_type` igual a `MESSAGE_TYPE_TRANSACTIONAL` ignora totalmente essa exclusão, assim como ocorre com os grupos de controle do aplicativo.

Definir `holdout_percentage` junto com `control_group`, ou um `holdout_percentage` acima de `20`, retorna `400`:

```json title="Invalid holdout_percentage"
{
  "code": 3,
  "message": "invalid argument",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.BadRequest",
      "fieldViolations": [
        {
          "field": "holdout_percentage",
          "description": "holdout_percentage and control_group are mutually exclusive"
        }
      ]
    },
    {
      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
      "reason": "InvalidHoldoutPercentage",
      "domain": "api.pushwoosh.com",
      "metadata": {}
    }
  ]
}
```

### Exemplo: Enviar para um segmento

```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

Envia para uma lista explícita de destinatários.

| Campo | Tipo | Descrição |
|---|---|---|
| `schedule` | [`Schedule`](#schedule) | Obrigatório. |
| `application` | string | [Código do Aplicativo](/pt/developer/api-reference/api-identifiers/#application-code). |
| `platforms` | array of [`Platform`](#platform-enum) | Plataformas que a mensagem direciona. |
| `test_devices` | bool | Se `true`, envia apenas para os dispositivos de teste do aplicativo. |
| `hwids` | `{ "list": [string, ...] }` | Envia apenas para estes [hwids](/pt/developer/pushwoosh-knowledge-hub/device-identifiers/#hwid). |
| `users` | `{ "list": [string, ...] }` | Envia apenas para estes [IDs de usuário](/pt/developer/pushwoosh-knowledge-hub/users-userids/). |
| `push_tokens` | `{ "list": [string, ...] }` | Envia apenas para estes [tokens de push](/pt/developer/pushwoosh-knowledge-hub/device-identifiers/#push-token). |
| `payload` | [`Payload`](/pt/developer/api-reference/messaging-api-v2/payload-reference/) | Payload de Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber / Facebook Messenger. |
| `email_payload` | [`EmailPayload`](/pt/developer/api-reference/messaging-api-v2/email-payload-reference/) | Payload de e-mail. |
| `return_unknown_identifiers` | bool | Quando `true`, o `unknown_identifiers` da resposta lista os identificadores que não foram encontrados. |
| `use_latest_user_device` | bool | Aplica-se apenas quando você direciona `users`. Mesmo comportamento que no `NotifySegment` acima — entrega uma mensagem por usuário em vez de uma por dispositivo, com escopo para `platforms`. O padrão é `false`. |
| `campaign`, `campaign_name`, `frequency_capping`, `send_rate`, `message_type`, `dynamic_content_placeholders`, `meta_data` | | Veja `NotifySegment` acima. |

`test_devices`, `hwids`, `users` e `push_tokens` são mutuamente exclusivos. Exatamente um deve ser definido.

### Exemplo: Transacional por IDs de usuário

```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
    }
  }'
```

<span id="response" />

## Resposta

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

| Campo | Tipo | Descrição |
|---|---|---|
| `message_code` | string | [Código da mensagem](/pt/developer/api-reference/api-identifiers/#message-code) único. Use-o com [`/getMessageDetails`](/pt/developer/api-reference/messages-api/#getmessagedetails) e endpoints de estatísticas de mensagens. |
| `unknown_identifiers` | array of string | Identificadores não encontrados na conta. Preenchido apenas quando `return_unknown_identifiers: true` foi definido no tipo `transactional`. |

## Tipos compartilhados

### Schedule

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

| Campo | Tipo | Descrição |
|---|---|---|
| `at` | timestamp | Tempo de envio absoluto (RFC 3339). Se estiver no passado, o Pushwoosh substitui pelo momento em que a solicitação foi recebida. Com `follow_user_timezone` não definido ou `false`, isso significa que a mensagem é enviada imediatamente para todos. Veja o aviso abaixo para `follow_user_timezone: true`. Máximo de 30 dias no futuro. |
| `after` | duration | Alternativa a `at`. Enviar após este deslocamento de "agora" (por exemplo, `"3600s"`). Máximo de 30 dias. |
| `follow_user_timezone` | bool | Quando `true`, cada dispositivo recebe a mensagem em `at` no seu fuso horário local. |
| `past_timezones_behaviour` | enum | `PAST_TIMEZONES_BEHAVIOUR_SEND_IMMEDIATELY` (padrão), `PAST_TIMEZONES_BEHAVIOUR_DO_NOT_SEND` ou `PAST_TIMEZONES_BEHAVIOUR_NEXT_DAY`. Apenas significativo quando `follow_user_timezone` é `true` ou `best_time_to_send` está definido. |
| `best_time_to_send` | timestamp | Opcional. Apenas para envios a segmentos. Cada dispositivo recebe a mensagem no seu próprio melhor horário dentro de 24 horas a partir deste momento. Dispositivos sem melhor horário a recebem na data e hora de `at` / `after` no seu fuso horário local. Consulte [Melhor horário de envio](#best-time-to-send). |

<Aside type="caution" title="Um horário de envio no passado não é instantâneo para todos com follow_user_timezone">
Com `follow_user_timezone: true`, o "agora" substituído ainda é dividido em faixas de horário local por dispositivo, e não entregue a todos os dispositivos de uma vez. Os fusos atrás do UTC ainda não chegaram a esse momento localmente, então recebem a mensagem até 12 horas depois. Os fusos à frente do UTC já passaram desse momento localmente, então seguem `past_timezones_behaviour`: enviada agora, ignorada (`DO_NOT_SEND`) ou adiada em um dia (`NEXT_DAY`) nesse mesmo horário local. A mesma divisão se aplica ao envio alternativo de [`best_time_to_send`](#best-time-to-send).
</Aside>

<span id="best-time-to-send" />

#### Melhor horário de envio

`best_time_to_send` é o equivalente na API da opção [Melhor horário](/pt/product/messaging-channels/push-notifications/send-push-notifications/one-time-push/#best-time-paid-subscription-required) do Control Panel. `at` / `after` define o envio alternativo para dispositivos sem dados suficientes para um melhor horário. O Pushwoosh usa a data e hora UTC de `at` / `after` e entrega o envio alternativo nessa data e hora no fuso horário local de cada dispositivo, como com `follow_user_timezone: true`. Isso se aplica implicitamente: deixe `follow_user_timezone` sem definir, pois `true` é rejeitado com `BestTimeToSendWithUserTimezone`. No exemplo abaixo, os dispositivos sem melhor horário recebem a mensagem às 18:00, horário local, em 1º de maio. Onde esse horário local já tiver passado quando o envio começar, aplica-se `past_timezones_behaviour`.

```json
{
  "at": "2026-05-01T18:00:00Z",
  "best_time_to_send": "2026-05-01T00:00:00Z"
}
```

O Pushwoosh rejeita a solicitação com `400`, a menos que todas estas condições sejam atendidas:

- A solicitação usa o tipo `segment`. Envios `transactional` não suportam `best_time_to_send`.
- `follow_user_timezone` não está definido ou é `false`.
- O horário de envio de `at` / `after` está no futuro. Um `at` no passado, `after: "0s"` ou um `after` omitido contam como "enviar agora" e são rejeitados.
- `best_time_to_send` não é anterior à próxima hora cheia nem está a mais de 30 dias no futuro. Ele é arredondado para baixo até a hora cheia.
- O horário de envio de `at` / `after` não é posterior a `best_time_to_send` mais 24 horas.

O `reason` do erro (no detalhe `ErrorInfo`) indica a verificação que falhou:

| `reason` | Causa |
|---|---|
| `BestTimeToSendWithUserTimezone` | `follow_user_timezone` é `true`. |
| `BestTimeToSendTooEarly` | `best_time_to_send` é anterior à próxima hora cheia. |
| `BestTimeToSendTooFarInFuture` | `best_time_to_send` está a mais de 30 dias no futuro. |
| `SendDateAfterBestTimeToSend` | `at` / `after` é posterior a `best_time_to_send` mais 24 horas. |
| `BestTimeToSendNotAllowed` | `best_time_to_send` está definido em um envio `transactional`. |
| `BestTimeToSendWithSendNow` | `at` / `after` resulta em "agora" (`at` no passado ou `after` igual a zero). |

### FrequencyCapping

Limites de frequência por usuário para envios de marketing. Para desativar o limite, omita `frequency_capping` completamente, ou envie `days: 0` junto com `count: 0`.

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

- `days` (int, 1–30, ou `0` para desativar o limite): janela de retrospectiva. Deve ser enviado junto com `count` — se um for `0`, o outro também deve ser `0`; enviar um como `0` enquanto o outro é diferente de zero retorna `400`.
- `count` (int, 1 ou superior, ou `0` para desativar o limite): número máximo de mensagens permitidas dentro de `days`. Mesma regra de pareamento que `days` acima.
- `exclude` (bool): exclui permanentemente os usuários que já atingiram o limite.
- `avoid` (bool): evita suavemente os usuários que já atingiram o limite (eles ainda contam para as análises).

<Aside type="caution" title="Importante">
Enviar `days` e `count` com valores de zero incompatíveis (por exemplo, `{"days": 0, "count": 5}`) retorna `400`. Esta validação é uma alteração que quebra a compatibilidade com `Notify` — clientes que anteriormente dependiam de um `0` solitário ser silenciosamente ignorado agora receberão um erro.
</Aside>

### SendRate

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

Controla a velocidade do envio. `value` é o número de mensagens por `bucket`; um `bucket` típico é `"1s"`.

<span id="platform-enum" />

### Enum Platform

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

<span id="messagetype-enum" />

### Enum MessageType

- `MESSAGE_TYPE_UNSPECIFIED`: equivalente a `MESSAGE_TYPE_MARKETING`.
- `MESSAGE_TYPE_MARKETING`: sujeito à filtragem do grupo de controle e ao limite de frequência.
- `MESSAGE_TYPE_TRANSACTIONAL`: ignora a filtragem do grupo de controle e o limite de frequência. Use para confirmações de pedido, OTPs e fluxos críticos semelhantes.

## Relacionados

<CardGrid>
  <LinkCard title="Notify em lote" href="/developer/api-reference/messaging-api-v2/notify-batch/" />
  <LinkCard title="Cancel" href="/developer/api-reference/messaging-api-v2/cancel/" />
  <LinkCard title="Referência de Payload" href="/developer/api-reference/messaging-api-v2/payload-reference/" />
  <LinkCard title="Referência de payload de e-mail" href="/developer/api-reference/messaging-api-v2/email-payload-reference/" />
  <LinkCard title="Migração da v1" href="/developer/api-reference/messaging-api-v2/migration-from-v1/" />
</CardGrid>