跳到内容

Migration from v1

此内容尚未提供您的语言版本。

This guide maps every legacy /create*Message field onto its Messaging API v2 equivalent. Use it as a reference while porting existing integrations.

High-level differences

Anchor link to
Aspectv1v2
Endpoint per channelseparate method per channel (/createMessage, /createEmailMessage, /createSMSMessage, /createKakaoMessage, …)single endpoint — POST /messaging/v2/notify
Authauth field in the request bodyAuthorization: Token <API_TOKEN> header
Targetingmixed: filter + conditions + devices + users on the same requestexplicit split: NotifySegment vs NotifyTransactional
Contentflat content + sibling platform blocksnested payload.content.localized_content.{locale}.{platform}
ResponseMessageCode[]message_code + optional unknown_identifiers

From /createMessage

Anchor link to

v1 notifications[*] entries become individual Notify requests (one message each). If a v1 call has multiple entries, issue one Notify per entry.

Targeting decision. If the v1 entry uses devices or users (explicit lists), map it to transactional. Otherwise map it to segment.

Request-level fields

Anchor link to
  • applicationsegment.application or transactional.application (same app-code format).
  • applications_group: not supported in v2. Use multiple per-app requests.
  • auth: moved to the Authorization header, no longer in the body.

Scheduling

Anchor link to
  • send_date ("YYYY-MM-DD HH:mm" or "now") → schedule.at (RFC 3339 UTC timestamp). To reproduce v1 "now", set schedule.at to the current time. Any timestamp in the past is sent immediately.
  • ignore_user_timezoneschedule.follow_user_timezone. Inverted: ignore_user_timezone: true becomes follow_user_timezone: false.
  • timezone: not supported. v2 always uses UTC for at. Convert client-side.
  • filter (segment name) → segment.code.
  • conditions ([[tag, op, value], ...]) → segment.expression. Rewrite to a seglang expression. In seglang, * is logical AND and app-specific tags are referenced as Tag("<application-code>", "<tag>", <op>, <value>). Example: [["Country","EQ","BR"],["Language","EQ","pt"]] with conditions_operator: ANDTag("XXXXX-XXXXX", "Country", EQ, "br") * Tag("XXXXX-XXXXX", "Language", EQ, "pt").
  • conditions_operator (AND / OR): folded into segment.expression.
  • devices (hwids or push tokens) → transactional.hwids.list or transactional.push_tokens.list. v2 separates the two: hwids go into hwids, raw push tokens into push_tokens.
  • userstransactional.users.list.
  • platforms (numeric codes [1, 3, …]) → segment.platforms or transactional.platforms (string enums ["IOS", "ANDROID", …]). See Platform enum.
  • content (string) → payload.content.localized_content.default.{platform}.body. In v2, content is always per-locale and per-platform. Put a plain v1 string under the special "default" key (catch-all translation, see Locale selection).
  • content ({locale: text}) → payload.content.localized_content.{locale}.{platform}.body. Duplicate the body into each targeted platform block.
  • presetpayload.preset.
  • datapayload.custom_data.
  • rich_mediapayload.open_action.rich_media.code.
  • linkpayload.open_action.link.url.
  • minimize_link (0 or 2) → payload.open_action.link.shortener (NONE or BITLY).
  • inbox_imagepayload.content.localized_content.{locale}.{platform}.inbox.image_url (each platform block has its own inbox).
  • inbox_datepayload.content.localized_content.{locale}.{platform}.inbox.expiration_date.
  • inbox_days: not supported. Convert to an absolute expiration_date client-side.

Delivery controls

Anchor link to
  • dynamic_content / dynamic_content_placeholdersdynamic_content_placeholders on segment or transactional.
  • campaigncampaign on segment or transactional.
  • capping_daysfrequency_capping.days.
  • capping_countfrequency_capping.count.
  • send_rate (int) → send_rate.value with send_rate.bucket: "1s".
  • message_type ("marketing" / "transactional") → message_type (MESSAGE_TYPE_MARKETING / MESSAGE_TYPE_TRANSACTIONAL).

Not supported in v2

Anchor link to
  • transactionId: no direct equivalent. Track correlation on your side.
  • template_bindings: Liquid template bindings are not available in v2. Keep using v1 if you rely on them.

Platform-specific blocks

Anchor link to

v1 accepts platform-specific parameters at the top level of each notifications[*] entry (ios, android, safari, chrome, …). In v2 they move inside the 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" }
}
}
}
}

Field names within platform blocks differ in places. See the Payload reference for the exact v2 names.

Example: Before and after

Anchor link to

v1 /createMessage (push to a 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"
}
}

From /createTargetedMessage

Anchor link to

/createTargetedMessage maps to transactional in most cases or to segment if you were using it purely as a cross-app devices_filter with no explicit identifiers.

  • devices_filtersegment.expression (seglang) or segment.filter_expression (structured).
  • contentpayload.content.localized_content.{locale}.{platform}.body.
  • All other fields, same as /createMessage above.

From /createEmailMessage

Anchor link to

Move to Notify with platforms: ["EMAIL"] and an email_payload block. Full reference: Email payload reference.

  • subjectemail_payload.subject (map keyed by locale. Wrap single-locale values in {"en": "..."}).
  • content (HTML) → email_payload.body.
  • email_templateemail_payload.email_template.
  • from / from_nameemail_payload.from ({ "name": "...", "email": "..." }).
  • reply_to / reply_to_nameemail_payload.reply_to.
  • list_unsubscribeemail_payload.list_unsubscribe.
  • attachmentsemail_payload.attachments ([{ "name": "...", "content": "<base64>" }]).
  • Targeting, schedule, campaign, etc., same as /createMessage.

From /createSMSMessage

Anchor link to

Move to Notify with platforms: ["SMS"]. The SMS body is delivered through the app’s configured SMS provider. Put the content in payload.content.localized_content.{locale}.{platform}.body on any filled platform block.

SMS-specific provider options (sender ID, etc.) continue to come from the app’s SMS configuration rather than the request body.

From /createKakaoMessage

Anchor link to

Move to Notify with platforms: ["KAKAO"], using payload.content.localized_content.{locale}.kakao:

  • template_idkakao.template.
  • contentkakao.content.
  • variableskakao.content_variables (JSON-stringified).

From /createWhatsAppMessage

Anchor link to

Move to Notify with platforms: ["WHATS_APP"], using payload.content.localized_content.{locale}.whatsapp:

  • content (free-form text) → whatsapp.content. Delivered by Meta only inside the 24-hour customer service window.
  • content_idwhatsapp.content_id. Name of a pre-approved Meta template.
  • languagewhatsapp.language. Meta-template locale (e.g. "en_US"). Independent of the outer LocalizedContent locale key.
  • content_variables (object in v1) → whatsapp.content_variables (JSON-stringified object). Example v1 {"1": "John"} becomes v2 "{\"1\":\"John\"}".
  • button_url_variables (object) → whatsapp.button_url_variables (JSON-stringified).
  • header_variables (object) → whatsapp.header_variables (JSON-stringified).
  • presetpayload.preset (generic preset on the payload level).
  • Targeting: the WhatsApp phone number that in v1 went into devices (e.g. "whatsapp:+1234567890") must be registered via /registerDevice against a user. In v2, target the resulting user with transactional.users.list (or the hwid via transactional.hwids.list).
  • use_auto_registration: not supported. Register the WhatsApp number before sending.

From /createLineMessage

Anchor link to

Move to Notify with platforms: ["LINE"], using payload.content.localized_content.{locale}.line:

  • content (plain text) → line.content.
  • preset (LINE preset code) → line.template. The v2 field stores a code that references a LINE template configured in the Pushwoosh Control Panel.
  • Inline template (v1 image, carousel, or flex message structures): not supported directly in v2. Pre-configure the rich message as a LINE preset in the Control Panel and reference it through line.template.
  • Targeting: the v1 devices list (LINE user IDs registered through the SDK / /registerDevice) becomes transactional.users.list (or the hwid via transactional.hwids.list) in v2.

Response differences

Anchor link to

v1 /createMessage returns:

{
"status_code": 200,
"status_message": "OK",
"response": { "Messages": ["XXXXX-XXXXX-AAAAA"] }
}

v2 Notify returns:

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

Non-200 responses follow the standard gRPC-Gateway error envelope ({ "code": ..., "message": ..., "details": [...] }) instead of the v1 status_code / status_message pair.