Migration depuis la v1
Ce guide mappe chaque champ hérité de /create*Message sur son équivalent dans l’API de Messagerie v2. Utilisez-le comme référence lors de la migration de vos intégrations existantes.
Différences de haut niveau
Anchor link to| Aspect | v1 | v2 |
|---|---|---|
| Point de terminaison par canal | méthode distincte par canal (/createMessage, /createEmailMessage, /createSMSMessage, /createKakaoMessage, …) | point de terminaison unique — POST /messaging/v2/notify |
| Authentification | champ auth dans le corps de la requête | en-tête Authorization: Token <API_TOKEN> |
| Ciblage | mixte : filter + conditions + devices + users dans la même requête | séparation explicite : NotifySegment vs NotifyTransactional |
| Contenu | contenu plat + blocs de plateforme frères | payload.content.localized_content.{locale}.{platform} imbriqué |
| Réponse | MessageCode[] | message_code + unknown_identifiers optionnel |
Depuis /createMessage
Anchor link toLes entrées notifications[*] de la v1 deviennent des requêtes Notify individuelles (un message chacune). Si un appel v1 a plusieurs entrées, émettez une requête Notify par entrée.
Décision de ciblage. Si l’entrée v1 utilise devices ou users (listes explicites), mappez-la sur transactional. Sinon, mappez-la sur segment.
Champs au niveau de la requête
Anchor link toapplication→segment.applicationoutransactional.application(même format de code d’application).applications_group: non pris en charge dans la v2. Utilisez plusieurs requêtes par application.auth: déplacé vers l’en-têteAuthorization, n’est plus dans le corps.
Planification
Anchor link tosend_date("AAAA-MM-JJ HH:mm"ou"now") →schedule.at(horodatage UTC RFC 3339). Pour reproduire"now"de la v1, définissezschedule.atsur l’heure actuelle. Tout horodatage dans le passé est envoyé immédiatement.ignore_user_timezone→schedule.follow_user_timezone. Inversé :ignore_user_timezone: truedevientfollow_user_timezone: false.timezone: non pris en charge. La v2 utilise toujours UTC pourat. Convertissez côté client.
Ciblage
Anchor link tofilter(nom du segment) →segment.code.conditions([[tag, op, value], ...]) →segment.expression. Réécrivez en une expression seglang. En seglang,*est un ET logique et les tags spécifiques à l’application sont référencés commeTag("<application-code>", "<tag>", <op>, <value>). Exemple :[["Country","EQ","BR"],["Language","EQ","pt"]]avecconditions_operator: AND→Tag("XXXXX-XXXXX", "Country", EQ, "br") * Tag("XXXXX-XXXXX", "Language", EQ, "pt").conditions_operator(AND/OR) : intégré danssegment.expression.devices(hwids ou push tokens) →transactional.hwids.listoutransactional.push_tokens.list. La v2 sépare les deux : les hwids vont danshwids, les push tokens bruts danspush_tokens.users→transactional.users.list.platforms(codes numériques[1, 3, …]) →segment.platformsoutransactional.platforms(énumérations de chaînes["IOS", "ANDROID", …]). Voir l’énumération Platform.
Contenu
Anchor link tocontent(chaîne) →payload.content.localized_content.default.{platform}.body. Dans la v2, le contenu est toujours par locale et par plateforme. Placez une chaîne v1 simple sous la clé spéciale"default"(traduction fourre-tout, voir Sélection de la locale).content({locale: text}) →payload.content.localized_content.{locale}.{platform}.body. Dupliquez le corps dans chaque bloc de plateforme ciblé.preset→payload.preset.data→payload.custom_data.rich_media→payload.open_action.rich_media.code.link→payload.open_action.link.url.minimize_link(0ou2) →payload.open_action.link.shortener(NONEouBITLY).inbox_image→payload.content.localized_content.{locale}.{platform}.inbox.image_url(chaque bloc de plateforme a son propreinbox).inbox_date→payload.content.localized_content.{locale}.{platform}.inbox.expiration_date.inbox_days: non pris en charge. Convertissez en uneexpiration_dateabsolue côté client.
Contrôles de livraison
Anchor link todynamic_content/dynamic_content_placeholders→dynamic_content_placeholderssursegmentoutransactional.campaign→campaignsursegmentoutransactional.capping_days→frequency_capping.days.capping_count→frequency_capping.count.send_rate(entier) →send_rate.valueavecsend_rate.bucket: "1s".message_type("marketing"/"transactional") →message_type(MESSAGE_TYPE_MARKETING/MESSAGE_TYPE_TRANSACTIONAL).
Non pris en charge dans la v2
Anchor link totransactionId: pas d’équivalent direct. Suivez la corrélation de votre côté.template_bindings: les liaisons de modèles Liquid ne sont pas disponibles dans la v2. Continuez à utiliser la v1 si vous en dépendez.
Blocs spécifiques à la plateforme
Anchor link toLa v1 accepte les paramètres spécifiques à la plateforme au niveau supérieur de chaque entrée notifications[*] (ios, android, safari, chrome, …). Dans la v2, ils se déplacent à l’intérieur de la locale :
// v1"notifications": [{ "content": "Hello", "ios": { "title": "Hi", "sound": "default.caf" }, "android": { "header": "Hi", "led": "#ff0000" }}]
// v2"payload": { "content": { "localized_content": { "en": { "ios": { "title": "Hi", "body": "Hello", "sound": "default.caf" }, "android": { "title": "Hi", "body": "Hello", "led_color": "#ff0000" } } } }}Les noms de champs dans les blocs de plateforme diffèrent par endroits. Consultez la Référence du payload pour les noms exacts de la v2.
Exemple : Avant et après
Anchor link tov1 /createMessage (push vers un segment) :
{ "request": { "application": "XXXXX-XXXXX", "auth": "YOUR_API_TOKEN", "notifications": [{ "send_date": "2026-05-01 12:00", "content": "Hello!", "platforms": [1, 3], "filter": "active_users", "campaign": "YYYYY-YYYYY", "capping_days": 7, "capping_count": 3, "message_type": "marketing" }] }}v2 /messaging/v2/notify :
{ "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" }, "frequency_capping": { "days": 7, "count": 3 }, "campaign": "YYYYY-YYYYY", "message_type": "MESSAGE_TYPE_MARKETING" }}Depuis /createTargetedMessage
Anchor link to/createTargetedMessage se mappe sur transactional dans la plupart des cas ou sur segment si vous l’utilisiez uniquement comme un devices_filter inter-applications sans identifiants explicites.
devices_filter→segment.expression(seglang) ousegment.filter_expression(structuré).content→payload.content.localized_content.{locale}.{platform}.body.- Tous les autres champs, comme pour
/createMessageci-dessus.
Depuis /createEmailMessage
Anchor link toPassez à Notify avec platforms: ["EMAIL"] et un bloc email_payload. Référence complète : Référence du payload d’e-mail.
subject→email_payload.subject(mappe indexée par locale. Encadrez les valeurs à locale unique dans{"en": "..."}).content(HTML) →email_payload.body.email_template→email_payload.email_template.from/from_name→email_payload.from({ "name": "...", "email": "..." }).reply_to/reply_to_name→email_payload.reply_to.list_unsubscribe→email_payload.list_unsubscribe.attachments→email_payload.attachments([{ "name": "...", "content": "<base64>" }]).- Ciblage, planification, campagne, etc., comme pour
/createMessage.
Depuis /createSMSMessage
Anchor link toPassez à Notify avec platforms: ["SMS"]. Le corps du SMS est livré via le fournisseur SMS configuré de l’application. Placez le contenu dans payload.content.localized_content.{locale}.{platform}.body sur n’importe quel bloc de plateforme rempli.
Les options spécifiques au fournisseur SMS (ID de l’expéditeur, etc.) continuent de provenir de la configuration SMS de l’application plutôt que du corps de la requête.
Depuis /createKakaoMessage
Anchor link toPassez à Notify avec platforms: ["KAKAO"], en utilisant payload.content.localized_content.{locale}.kakao :
template_id→kakao.template.content→kakao.content.variables→kakao.content_variables(chaîne JSON).
Depuis /createWhatsAppMessage
Anchor link toPassez à Notify avec platforms: ["WHATS_APP"], en utilisant payload.content.localized_content.{locale}.whatsapp :
content(texte libre) →whatsapp.content. Livré par Meta uniquement dans la fenêtre de service client de 24 heures.content_id→whatsapp.content_id. Nom d’un modèle Meta pré-approuvé.language→whatsapp.language. Locale du modèle Meta (par ex."en_US"). Indépendant de la clé de localeLocalizedContentexterne.content_variables(objet en v1) →whatsapp.content_variables(objet sous forme de chaîne JSON). Exemple v1{"1": "John"}devient v2"{\"1\":\"John\"}".button_url_variables(objet) →whatsapp.button_url_variables(chaîne JSON).header_variables(objet) →whatsapp.header_variables(chaîne JSON).preset→payload.preset(preset générique au niveau du payload).- Ciblage : le numéro de téléphone WhatsApp qui, dans la v1, allait dans
devices(par ex."whatsapp:+1234567890") doit être enregistré via/registerDevicepour un utilisateur. Dans la v2, ciblez l’utilisateur résultant avectransactional.users.list(ou le hwid viatransactional.hwids.list). use_auto_registration: non pris en charge. Enregistrez le numéro WhatsApp avant l’envoi.
Depuis /createLineMessage
Anchor link toPassez à Notify avec platforms: ["LINE"], en utilisant payload.content.localized_content.{locale}.line :
content(texte brut) →line.content.preset(code de preset LINE) →line.template. Le champ v2 stocke un code qui référence un modèle LINE configuré dans le Panneau de Contrôle Pushwoosh.- Modèle en ligne (structures de message image, carrousel ou flex de la v1) : non pris en charge directement dans la v2. Pré-configurez le message riche comme un preset LINE dans le Panneau de Contrôle et référencez-le via
line.template. - Ciblage : la liste
devicesde la v1 (ID utilisateur LINE enregistrés via le SDK //registerDevice) devienttransactional.users.list(ou le hwid viatransactional.hwids.list) dans la v2.
Différences de réponse
Anchor link toLa v1 /createMessage retourne :
{ "status_code": 200, "status_message": "OK", "response": { "Messages": ["XXXXX-XXXXX-AAAAA"] }}La v2 Notify retourne :
{ "result": { "message_code": "XXXXX-XXXXX-AAAAA", "unknown_identifiers": [] }}Les réponses non-200 suivent l’enveloppe d’erreur standard gRPC-Gateway ({ "code": ..., "message": ..., "details": [...] }) au lieu de la paire status_code / status_message de la v1.