Passer au contenu

Notify

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

Crée et planifie un message unique.

Structure de la requête

Anchor link to

Le 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.
Shape
{
"segment": { ... }, // OU
"transactional": { ... },
"transaction_id": "unique-uuid"
}
ChampTypeDescription
transaction_idstringOptionnel. 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 to

Cible 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.

ChampTypeDescription
scheduleScheduleQuand et comment envoyer. Requis.
applicationstringCode d’application.
platformsarray of PlatformPlateformes ciblées par le message.
codestringCode de segment d’un segment enregistré à l’avance. Mutuellement exclusif avec expression et filter_expression.
expressionstringExpression Seglang, évaluée pour cet envoi uniquement — aucun segment enregistré n’est requis. Mutuellement exclusif avec code et filter_expression.
filter_expressionFilterExpressionLa 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.
payloadPayloadPayload Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber / Facebook Messenger. Mutuellement exclusif avec email_payload.
email_payloadEmailPayloadPayload d’e-mail.
campaignstringCode de campagne auquel attribuer ce message.
campaign_namestringNom 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_cappingFrequencyCappingLimites de fréquence par utilisateur.
send_rateSendRateLimitation du débit pour l’envoi.
silent_hoursSilentHoursFacultatif. Envoie le message sans tenir compte des heures de silence de l’application.
message_typeMessageTypeMESSAGE_TYPE_MARKETING (par défaut) ou MESSAGE_TYPE_TRANSACTIONAL. Contrôle le filtrage du groupe de contrôle.
dynamic_content_placeholdersmap<string, string>Remplace les placeholders dans le contenu.
meta_dataobjectMétadonnées de forme libre transmises aux analyses en aval.
use_latest_user_deviceboolSi 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).
geo_zoneGeoZoneFacultatif. Restreint l’audience aux appareils dont la dernière position enregistrée se trouve à l’intérieur d’un cercle que vous définissez dans cette requête. Il est combiné avec code, expression ou filter_expression par AND : un appareil doit correspondre au segment et se trouver dans le cercle. Les appareils sans position enregistrée sont ignorés. Non disponible dans NotifyTransactional.
control_groupstringCode 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_percentageuint32Pré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 :

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": {}
}
]
}

Exemple : Envoi à un segment

Anchor link to
Terminal window
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

Anchor link to

Envoie à une liste explicite de destinataires.

ChampTypeDescription
scheduleScheduleRequis.
applicationstringCode d’application.
platformsarray of PlatformPlateformes ciblées par le message.
test_devicesboolSi 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.
payloadPayloadPayload Push / SMS / Telegram / Kakao / LINE / WhatsApp / Viber / Facebook Messenger.
email_payloadEmailPayloadPayload d’e-mail.
return_unknown_identifiersboolSi true, la liste unknown_identifiers de la réponse contient les identifiants qui n’ont pas été trouvés.
registration_typeRegistrationTypeComportement pour les hwids qui ne sont pas encore enregistrés dans Pushwoosh. La valeur par défaut est REGISTRATION_TYPE_DEFAULT, qui les ignore. Définissez REGISTRATION_TYPE_FORCE pour enregistrer de nouvelles adresses e-mail ou de nouveaux numéros de téléphone et leur envoyer le message dans la même requête.
use_latest_user_deviceboolS’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, silent_hours, message_type, dynamic_content_placeholders, meta_dataVoir NotifySegment ci-dessus.

test_devices, hwids, users et push_tokens sont mutuellement exclusifs. Un seul doit être défini.

Envoyer à de nouvelles adresses e-mail et de nouveaux numéros de téléphone

Anchor link to

Pour l’e-mail, les SMS, WhatsApp, LINE, Viber et Kakao, le hwid est la destination elle-même, par exemple l’adresse e-mail ou le numéro de téléphone. Pour envoyer à un hwid qui n’est pas encore enregistré, indiquez-le dans hwids et définissez registration_type sur REGISTRATION_TYPE_FORCE. Pushwoosh l’enregistre et livre le message dans la même requête : vous n’avez donc pas besoin d’appeler /registerDevice ou /registerEmail au préalable.

registration_type fonctionne uniquement avec hwids. Avec users, un ID utilisateur inconnu n’est pas créé, quelle que soit la valeur de registration_type.

Écrivez chaque hwid dans le format sous lequel /registerDevice le stocke pour ce canal :

CanalFormat du hwidExemple
E-mailAdresse e-mailnew.customer@example.com
SMSNuméro de téléphone au format international+14155552671
WhatsAppNuméro de téléphone avec le préfixe whatsapp:whatsapp:+14155552671
KakaoNuméro de téléphone avec le préfixe kakao:kakao:+821012345678
ViberNuméro de téléphone avec le préfixe viber:. Pushwoosh ajoute le préfixe s’il est absentviber:+14155552671
LINEID utilisateur LINEU4af4980629a1b2c3d4e5f6a7b8c9d0e1

Conservez les préfixes whatsapp: et kakao:. Sans eux, le numéro est interprété comme un hwid SMS. Si ce numéro est déjà enregistré pour les SMS, l’envoi trouve le hwid SMS, qui ne correspond pas à la plateforme ciblée, et le destinataire est ignoré.

Pushwoosh vérifie les numéros de téléphone uniquement avec return_unknown_identifiers: true. Dans ce cas, un hwid SMS, WhatsApp ou Kakao qui n’est pas un numéro de téléphone valide n’est pas enregistré et est renvoyé dans unknown_identifiers. Sans cet indicateur, la valeur est enregistrée telle quelle.

REGISTRATION_TYPE_FORCE n’enregistre pas de hwids sur les plateformes push, Telegram ou Facebook Messenger, car elles nécessitent un jeton fourni par le SDK ou la messagerie. Un hwid inconnu sur ces plateformes est ignoré sans avertissement. Il n’est pas renvoyé dans unknown_identifiers, et rien ne lui est envoyé.

Pour WhatsApp, l’enregistrement d’un numéro n’ouvre pas la fenêtre de service client de 24 heures. Un numéro qui ne vous a pas encore écrit ne peut recevoir qu’un modèle préapprouvé défini dans whatsapp.content_id, et non un whatsapp.content libre.

Exemple : Envoi à une nouvelle adresse e-mail

Anchor link to
Terminal window
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": ["EMAIL"],
"hwids": { "list": ["new.customer@example.com"] },
"registration_type": "REGISTRATION_TYPE_FORCE",
"email_payload": {
"subject": { "en": "Welcome aboard" },
"body": "<p>Thanks for signing up!</p>"
},
"schedule": { "at": "2026-05-01T12:00:00Z" },
"message_type": "MESSAGE_TYPE_TRANSACTIONAL",
"return_unknown_identifiers": true
}
}'

Exemple : Transactionnel par ID utilisateur

Anchor link to
Terminal window
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
}
}'
{
"result": {
"message_code": "XXXXX-XXXXX-XXXXX",
"unknown_identifiers": []
}
}
ChampTypeDescription
message_codestringCode de message unique. Utilisez-le avec /getMessageDetails et les points de terminaison de statistiques de message.
unknown_identifiersarray of stringIdentifiants non trouvés sur le compte. Rempli uniquement pour un envoi transactional avec return_unknown_identifiers: true ou avec un ciblage par push_tokens. Les identifiants enregistrés via REGISTRATION_TYPE_FORCE n’y figurent pas.

/getMessageDetails ne trouve pas un message transactional envoyé immédiatement à moins de 10 utilisateurs et à moins de 10 appareils, car un tel message n’est pas stocké. Consultez Messages envoyés immédiatement à moins de 10 destinataires.

Aucun destinataire trouvé

Anchor link to

Avec return_unknown_identifiers: true ou un ciblage par push_tokens, Pushwoosh recherche chaque destinataire avant de créer le message. Si aucun d’eux n’est enregistré, Notify renvoie HTTP 400 avec cette erreur, et aucun message n’est créé :

{
"code": 9,
"message": "No recipients found",
"details": [ ... ]
}

Si au moins un destinataire est trouvé, la requête aboutit et les autres sont listés dans unknown_identifiers. Pour envoyer plutôt à de nouvelles adresses e-mail ou de nouveaux numéros de téléphone, définissez registration_type sur REGISTRATION_TYPE_FORCE.

Pour l’e-mail, les adresses non valides et celles qui ont déjà généré un rebond sont retirées avant cette vérification, sans figurer dans unknown_identifiers. S’il ne reste aucune adresse après cela, Notify renvoie 200 avec un message_code, mais aucun message n’est créé et rien n’est envoyé.

Types partagés

Anchor link to
{
"at": "2026-05-01T12:00:00Z",
"follow_user_timezone": true,
"past_timezones_behaviour": "PAST_TIMEZONES_BEHAVIOUR_SEND_IMMEDIATELY"
}
ChampTypeDescription
attimestampHeure d’envoi absolue (RFC 3339). Maximum 30 jours dans le futur. Avec follow_user_timezone non défini ou false, un at passé est remplacé par l’heure de réception de la requête : le message part donc immédiatement pour tout le monde. Avec follow_user_timezone: true, un at passé est conservé tel quel. Voir l’avertissement ci-dessous.
afterdurationAlternative à at. Envoyer après ce décalage par rapport à “maintenant” (par ex. "3600s"). Maximum 30 jours.
follow_user_timezoneboolSi true, chaque appareil reçoit le message à l’heure at dans son fuseau horaire local.
past_timezones_behaviourenumPAST_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_sendtimestampFacultatif. 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 to

best_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 envois transactional ne prennent pas en charge best_time_to_send.
  • follow_user_timezone n’est pas défini ou vaut false.
  • L’heure d’envoi issue de at / after est dans le futur. Un at passé, after: "0s" ou un after omis valent « envoyer maintenant » et sont rejetés.
  • best_time_to_send n’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 / after n’est pas postérieure à best_time_to_send plus 24 heures.

Le reason de l’erreur (dans le détail ErrorInfo) indique la vérification qui a échoué :

reasonCause
BestTimeToSendWithUserTimezonefollow_user_timezone vaut true.
BestTimeToSendTooEarlybest_time_to_send est antérieur à la prochaine heure pleine.
BestTimeToSendTooFarInFuturebest_time_to_send se situe à plus de 30 jours dans le futur.
SendDateAfterBestTimeToSendat / after est postérieur à best_time_to_send plus 24 heures.
BestTimeToSendNotAllowedbest_time_to_send est défini sur un envoi transactional.
BestTimeToSendWithSendNowat / after correspond à « maintenant » (at passé ou after nul).

Un cercle ponctuel pour geo_zone, défini dans la requête elle-même. Il ne s’agit pas d’une géozone enregistrée : les campagnes géolocalisées et l’API Geozones ne sont pas utilisées, et rien n’est stocké dans l’application.

{ "lat": 40.7128, "lng": -74.006, "range": 500 }
ChampTypeDescription
latdoubleLatitude du centre du cercle, en degrés. Obligatoire.
lngdoubleLongitude du centre du cercle, en degrés. Obligatoire.
rangedoubleRayon du cercle en mètres. Obligatoire.

FrequencyCapping

Anchor link to

Limites 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, ou 0 pour désactiver la limitation) : fenêtre de temps à analyser. Doit être envoyé avec count — si l’un est 0, l’autre doit aussi être 0 ; envoyer l’un à 0 alors que l’autre est non nul renvoie une erreur 400.
  • count (int, 1 ou plus, ou 0 pour désactiver la limitation) : nombre maximum de messages autorisés pendant la période days. Même règle de couplage que days ci-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).
{ "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".

SilentHours

Anchor link to
{ "avoid": true }

Les messages marketing respectent par défaut les heures de silence de l’application : pendant la période de silence, ils sont retenus jusqu’à sa fin ou ne sont pas envoyés, selon les paramètres du canal. Définissez avoid sur true pour envoyer ce message même pendant la période de silence. Les messages dont le message_type est MESSAGE_TYPE_TRANSACTIONAL ne sont jamais retenus par les heures de silence et n’ont donc pas besoin de ce champ.

Énumération Platform

Anchor link to

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

Énumération RegistrationType

Anchor link to
  • REGISTRATION_TYPE_DEFAULT : ignore les identifiants qui ne sont pas enregistrés dans Pushwoosh. Par défaut.
  • REGISTRATION_TYPE_NONE : envoie à chaque hwid listé sans enregistrer d’appareil pour celui-ci.
  • REGISTRATION_TYPE_FORCE : enregistre chaque hwid inconnu comme appareil sur le canal ciblé, puis lui envoie le message. S’applique à l’e-mail, aux SMS, à WhatsApp, LINE, Viber et Kakao.

Énumération MessageType

Anchor link to
  • MESSAGE_TYPE_UNSPECIFIED : équivalent à MESSAGE_TYPE_MARKETING.
  • MESSAGE_TYPE_MARKETING : soumis au filtrage du groupe de contrôle, à la limitation de fréquence et aux heures de silence.
  • MESSAGE_TYPE_TRANSACTIONAL : ignore le filtrage du groupe de contrôle, la limitation de fréquence et les heures de silence. À utiliser pour les confirmations de commande, les OTP et autres flux critiques similaires.

Articles connexes

Anchor link to