Notify
POST https://api.pushwoosh.com/messaging/v2/notify
Crée et planifie un message unique.
Structure de la requête
Anchor link toLe corps de la requête est un NotifyRequest avec exactement l’un des deux types :
segment: cible un segment d’audience par code de segment, ou — sans créer de segment au préalable — une expression seglang ou une expression de filtre structurée.transactional: envoie à une liste explicite de HWID, d’ID utilisateur, de jetons push ou d’appareils de test.
{ "segment": { ... }, // OU "transactional": { ... }, "transaction_id": "unique-uuid"}| Champ | Type | Description |
|---|---|---|
transaction_id | string | Optionnel. Clé d’idempotence pour la requête — fonctionne avec segment et transactional. Un appel répété avec le même transaction_id dans les 5 minutes renvoie le message_code original au lieu d’envoyer un message en double. Utilisez un UUID ou une autre valeur unique par envoi logique. |
NotifySegment
Anchor link toCible les utilisateurs qui correspondent à un segment d’audience ou à une expression de filtre. Définissez exactement l’un des champs suivants : code, expression ou filter_expression. Pour expression et filter_expression, aucun segment ne doit être créé au préalable — l’expression est évaluée en ligne pour cet envoi uniquement.
| Champ | Type | Description |
|---|---|---|
schedule | Schedule | Quand et comment envoyer. Requis. |
application | string | Code d’application. |
platforms | array of Platform | Plateformes ciblées par le message. |
code | string | Code de segment d’un segment enregistré à l’avance. Mutuellement exclusif avec expression et filter_expression. |
expression | string | Expression Seglang, évaluée pour cet envoi uniquement — aucun segment enregistré n’est requis. Mutuellement exclusif avec code et filter_expression. |
filter_expression | FilterExpression | La même logique que expression, sous forme d’objet structuré au lieu d’une chaîne seglang. Mutuellement exclusif avec code et expression. Le schéma FilterExpression n’est pas documenté publiquement — demandez-le au support de Pushwoosh si vous avez besoin de la forme structurée. |
payload | Payload | Payload Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber / Facebook Messenger. Mutuellement exclusif avec email_payload. |
email_payload | EmailPayload | Payload d’e-mail. |
campaign | string | Code de campagne auquel attribuer ce message. |
campaign_name | string | Nom interne de ce message, affiché comme le titre de la ligne dans Message History et dans son export. Sans rapport avec campaign ci-dessus. Ne regroupe pas les messages et n’affecte pas la livraison. Max 255 caractères, tronqué. Omettez-le ou laissez-le vide pour que le titre de la ligne provienne du contenu du payload lui-même. |
frequency_capping | FrequencyCapping | Limites de fréquence par utilisateur. |
send_rate | SendRate | Limitation du débit pour l’envoi. |
message_type | MessageType | MESSAGE_TYPE_MARKETING (par défaut) ou MESSAGE_TYPE_TRANSACTIONAL. Contrôle le filtrage du groupe de contrôle. |
dynamic_content_placeholders | map<string, string> | Remplace les placeholders dans le contenu. |
meta_data | object | Métadonnées de forme libre transmises aux analyses en aval. |
use_latest_user_device | bool | Si true, livre le message à l’appareil le plus récemment actif de chaque utilisateur (celui avec la dernière ouverture d’application la plus récente) au lieu de chaque appareil correspondant au segment. Limité aux platforms : seuls les appareils sur ces plateformes sont pris en compte, et si aucun n’a de données de dernière ouverture d’application, le premier appareil correspondant est utilisé au lieu d’annuler l’envoi. La valeur par défaut est false (envoyer à chaque appareil). |
control_group | string | Code ou nom du groupe d’exclusion propre à un envoi à appliquer à ce message. Il ne restreint pas les groupes de contrôle qui s’appliquent : chaque groupe de contrôle activé de l’application exclut des utilisateurs des envois marketing, que ce champ soit défini ou non. Mutuellement exclusif avec holdout_percentage. |
holdout_percentage | uint32 | Prélève cette part du segment, de 1 à 20, dans un groupe de contrôle limité à cet envoi, en plus des groupes de contrôle activés de l’application, afin de mesurer l’impact d’une seule campagne sans puiser dans les groupes partagés. 0 (par défaut) le désactive. Mutuellement exclusif avec control_group. |
Les appareils tirés dans le groupe d’exclusion sont exclus de la livraison de la même manière qu’avec les groupes de contrôle de l’application. Aucun message ne leur est envoyé, et le journal de suivi enregistre l’abandon sous la forme Device is in control group. Un message_type égal à MESSAGE_TYPE_TRANSACTIONAL ignore entièrement cette exclusion, comme pour les groupes de contrôle de l’application.
Définir holdout_percentage en même temps que control_group, ou un holdout_percentage supérieur à 20, renvoie 400 :
{ "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": {} } ]}Exemple : Envoi à un segment
Anchor link tocurl -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
Anchor link toEnvoie à une liste explicite de destinataires.
| Champ | Type | Description |
|---|---|---|
schedule | Schedule | Requis. |
application | string | Code d’application. |
platforms | array of Platform | Plateformes ciblées par le message. |
test_devices | bool | Si true, envoie uniquement aux appareils de test de l’application. |
hwids | { "list": [string, ...] } | Envoyer uniquement à ces HWID. |
users | { "list": [string, ...] } | Envoyer uniquement à ces ID utilisateur. |
push_tokens | { "list": [string, ...] } | Envoyer uniquement à ces jetons push. |
payload | Payload | Payload Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber / Facebook Messenger. |
email_payload | EmailPayload | Payload d’e-mail. |
return_unknown_identifiers | bool | Si true, la liste unknown_identifiers de la réponse contient les identifiants qui n’ont pas été trouvés. |
use_latest_user_device | bool | S’applique uniquement lorsque vous ciblez des users. Même comportement que dans NotifySegment ci-dessus — livre un message par utilisateur au lieu d’un par appareil, limité aux platforms. La valeur par défaut est false. |
campaign, campaign_name, frequency_capping, send_rate, message_type, dynamic_content_placeholders, meta_data | Voir NotifySegment ci-dessus. |
test_devices, hwids, users et push_tokens sont mutuellement exclusifs. Un seul doit être défini.
Exemple : Transactionnel par ID utilisateur
Anchor link tocurl -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 } }'Réponse
Anchor link to{ "result": { "message_code": "XXXXX-XXXXX-XXXXX", "unknown_identifiers": [] }}| Champ | Type | Description |
|---|---|---|
message_code | string | Code de message unique. Utilisez-le avec /getMessageDetails et les points de terminaison de statistiques de message. |
unknown_identifiers | array of string | Identifiants non trouvés sur le compte. Rempli uniquement lorsque return_unknown_identifiers: true a été défini sur le type transactional. |
Types partagés
Anchor link toSchedule
Anchor link to{ "at": "2026-05-01T12:00:00Z", "follow_user_timezone": true, "past_timezones_behaviour": "PAST_TIMEZONES_BEHAVIOUR_SEND_IMMEDIATELY"}| Champ | Type | Description |
|---|---|---|
at | timestamp | Heure d’envoi absolue (RFC 3339). Si elle est dans le passé, Pushwoosh la remplace par l’heure de réception de la requête. Avec follow_user_timezone non défini ou false, le message part donc immédiatement pour tout le monde. Voir l’avertissement ci-dessous pour follow_user_timezone: true. Maximum 30 jours dans le futur. |
after | duration | Alternative à at. Envoyer après ce décalage par rapport à “maintenant” (par ex. "3600s"). Maximum 30 jours. |
follow_user_timezone | bool | Si true, chaque appareil reçoit le message à l’heure at dans son fuseau horaire local. |
past_timezones_behaviour | enum | PAST_TIMEZONES_BEHAVIOUR_SEND_IMMEDIATELY (par défaut), PAST_TIMEZONES_BEHAVIOUR_DO_NOT_SEND, ou PAST_TIMEZONES_BEHAVIOUR_NEXT_DAY. N’a de sens que si follow_user_timezone est true ou si best_time_to_send est défini. |
best_time_to_send | timestamp | Facultatif. Envois à un segment uniquement. Chaque appareil reçoit le message à sa propre meilleure heure dans les 24 heures qui suivent ce moment. Les appareils sans meilleure heure le reçoivent à la date et à l’heure de at / after dans leur fuseau horaire local. Voir Meilleur moment d’envoi. |
Meilleur moment d’envoi
Anchor link tobest_time_to_send est l’équivalent API de l’option Meilleur moment du Control Panel. at / after définit l’envoi de repli pour les appareils qui n’ont pas assez de données pour déterminer une meilleure heure. Pushwoosh prend la date et l’heure UTC de at / after et livre l’envoi de repli à cette date et à cette heure dans le fuseau horaire local de chaque appareil, comme avec follow_user_timezone: true. Ce comportement s’applique implicitement : laissez follow_user_timezone non défini, car true est rejeté avec BestTimeToSendWithUserTimezone. Dans l’exemple ci-dessous, les appareils sans meilleure heure reçoivent le message à 18:00 heure locale le 1er mai. Là où cette heure locale est déjà passée au début de l’envoi, past_timezones_behaviour s’applique.
{ "at": "2026-05-01T18:00:00Z", "best_time_to_send": "2026-05-01T00:00:00Z"}Pushwoosh rejette la requête avec 400 sauf si toutes ces conditions sont remplies :
- La requête utilise le type
segment. Les envoistransactionalne prennent pas en chargebest_time_to_send. follow_user_timezonen’est pas défini ou vautfalse.- L’heure d’envoi issue de
at/afterest dans le futur. Unatpassé,after: "0s"ou unafteromis valent « envoyer maintenant » et sont rejetés. best_time_to_sendn’est pas antérieur à la prochaine heure pleine et ne se situe pas à plus de 30 jours dans le futur. Il est arrondi à l’heure pleine inférieure.- L’heure d’envoi issue de
at/aftern’est pas postérieure àbest_time_to_sendplus 24 heures.
Le reason de l’erreur (dans le détail ErrorInfo) indique la vérification qui a échoué :
reason | Cause |
|---|---|
BestTimeToSendWithUserTimezone | follow_user_timezone vaut true. |
BestTimeToSendTooEarly | best_time_to_send est antérieur à la prochaine heure pleine. |
BestTimeToSendTooFarInFuture | best_time_to_send se situe à plus de 30 jours dans le futur. |
SendDateAfterBestTimeToSend | at / after est postérieur à best_time_to_send plus 24 heures. |
BestTimeToSendNotAllowed | best_time_to_send est défini sur un envoi transactional. |
BestTimeToSendWithSendNow | at / after correspond à « maintenant » (at passé ou after nul). |
FrequencyCapping
Anchor link toLimites de fréquence par utilisateur pour les envois marketing. Pour désactiver la limitation, omettez entièrement frequency_capping, ou envoyez days: 0 avec count: 0.
{ "days": 7, "count": 3, "exclude": false, "avoid": true }days(int, 1–30, ou0pour désactiver la limitation) : fenêtre de temps à analyser. Doit être envoyé aveccount— si l’un est0, l’autre doit aussi être0; envoyer l’un à0alors que l’autre est non nul renvoie une erreur400.count(int, 1 ou plus, ou0pour désactiver la limitation) : nombre maximum de messages autorisés pendant la périodedays. Même règle de couplage quedaysci-dessus.exclude(bool) : exclure de manière stricte les utilisateurs qui ont déjà atteint la limite.avoid(bool) : éviter de manière souple les utilisateurs qui ont déjà atteint la limite (ils sont toujours comptabilisés dans les analyses).
SendRate
Anchor link to{ "value": 500, "bucket": "1s", "avoid": false }Limite le débit de l’envoi. value correspond au nombre de messages par bucket ; un bucket typique est "1s".
Énumération Platform
Anchor link toIOS, ANDROID, OSX, WINDOWS, AMAZON, SAFARI, CHROME, FIREFOX, IE, EMAIL, HUAWEI_ANDROID, SMS, WEB, KAKAO, TELEGRAM, LINE, WHATS_APP, VIBER, FB_MESSENGER.
Énumération MessageType
Anchor link toMESSAGE_TYPE_UNSPECIFIED: équivalent àMESSAGE_TYPE_MARKETING.MESSAGE_TYPE_MARKETING: soumis au filtrage du groupe de contrôle et à la limitation de fréquence.MESSAGE_TYPE_TRANSACTIONAL: ignore le filtrage du groupe de contrôle et la limitation de fréquence. À utiliser pour les confirmations de commande, les OTP et autres flux critiques similaires.