# Migration von v1

import { Badge } from '@astrojs/starlight/components';

Dieser Leitfaden ordnet jedes veraltete `/create*Message`-Feld seinem Äquivalent in der Messaging API v2 zu. Verwenden Sie ihn als Referenz beim Portieren bestehender Integrationen.

<Aside type="note">
Veraltete v1-Methoden sind deprecated, aber voll funktionsfähig. Es gibt kein festes Enddatum, sodass Sie in Ihrem eigenen Tempo migrieren können. Für neue Integrationen verwenden Sie die Messaging API v2.
</Aside>

## Allgemeine Unterschiede

| Aspekt | v1 | v2 |
|---|---|---|
| Endpunkt pro Kanal | separate Methode pro Kanal (`/createMessage`, `/createEmailMessage`, `/createSMSMessage`, `/createKakaoMessage`, …) | einzelner Endpunkt — `POST /messaging/v2/notify` |
| Auth | `auth`-Feld im Anfrage-Body | `Authorization: Token <API_TOKEN>`-Header |
| Targeting | gemischt: `filter` + `conditions` + `devices` + `users` in derselben Anfrage | explizite Trennung: `NotifySegment` vs `NotifyTransactional` |
| Inhalt | flaches `content` + nebengeordnete Plattformblöcke | verschachteltes `payload.content.localized_content.{locale}.{platform}` |
| Antwort | `MessageCode[]` | `message_code` + optional `unknown_identifiers` |

## Von `/createMessage`

v1 `notifications[*]`-Einträge werden zu einzelnen `Notify`-Anfragen (jeweils eine Nachricht). Wenn ein v1-Aufruf mehrere Einträge hat, führen Sie eine `Notify`-Anfrage pro Eintrag aus.

**Targeting-Entscheidung.** Wenn der v1-Eintrag `devices` oder `users` (explizite Listen) verwendet, ordnen Sie ihn `transactional` zu. Andernfalls ordnen Sie ihn `segment` zu.

### Felder auf Anfrageebene

- `application` → `segment.application` oder `transactional.application` (gleiches App-Code-Format).
- `applications_group`: wird in v2 nicht unterstützt. Verwenden Sie mehrere Anfragen pro App.
- `auth`: in den `Authorization`-Header verschoben, nicht mehr im Body.

### Zeitplanung

- `send_date` (`"YYYY-MM-DD HH:mm"` oder `"now"`) → `schedule.at` (RFC 3339 UTC-Zeitstempel). Um v1 `"now"` zu reproduzieren, setzen Sie `schedule.at` auf die aktuelle Zeit. Jeder Zeitstempel in der Vergangenheit wird sofort gesendet.
- `ignore_user_timezone` → `schedule.follow_user_timezone`. **Invertiert:** `ignore_user_timezone: true` wird zu `follow_user_timezone: false`.
- `timezone`: nicht unterstützt. v2 verwendet immer UTC für `at`. Konvertieren Sie clientseitig.

### Targeting

- `filter` (Segmentname) → `segment.code`.
- `conditions` (`[[tag, op, value], ...]`) → `segment.expression`. Schreiben Sie dies in einen [seglang](/de/developer/api-reference/segmentation-filters-api/segmentation-language/)-Ausdruck um. In seglang ist `*` ein logisches UND und app-spezifische Tags werden als `Tag("<application-code>", "<tag>", <op>, <value>)` referenziert. Beispiel: `[["Country","EQ","BR"],["Language","EQ","pt"]]` mit `conditions_operator: AND` → `Tag("XXXXX-XXXXX", "Country", EQ, "br") * Tag("XXXXX-XXXXX", "Language", EQ, "pt")`.
- `conditions_operator` (`AND` / `OR`): in `segment.expression` integriert.
- `devices` (HWIDs oder Push-Tokens) → `transactional.hwids.list` oder `transactional.push_tokens.list`. v2 trennt die beiden: HWIDs gehen in `hwids`, rohe Push-Tokens in `push_tokens`.
- `users` → `transactional.users.list`.
- `platforms` (numerische Codes `[1, 3, …]`) → `segment.platforms` oder `transactional.platforms` (String-Enums `["IOS", "ANDROID", …]`). Siehe [Platform enum](/de/developer/api-reference/messaging-api-v2/notify/#platform-enum).

### Inhalt

- `content` (String) → `payload.content.localized_content.default.{platform}.body`. In v2 ist der Inhalt immer pro Locale und pro Plattform. Setzen Sie einen einfachen v1-String unter den speziellen Schlüssel `"default"` (Catch-all-Übersetzung, siehe [Locale-Auswahl](/de/developer/api-reference/messaging-api-v2/payload-reference/#locale-selection-for-a-device)).
- `content` (`{locale: text}`) → `payload.content.localized_content.{locale}.{platform}.body`. Duplizieren Sie den Body in jeden anvisierten Plattformblock.
- `preset` → `payload.preset`.
- `data` → `payload.custom_data`.
- `rich_media` → `payload.open_action.rich_media.code`.
- `link` → `payload.open_action.link.url`.
- `minimize_link` (`0` oder `2`) → `payload.open_action.link.shortener` (`NONE` oder `BITLY`).
- `inbox_image` → `payload.content.localized_content.{locale}.{platform}.inbox.image_url` (jeder Plattformblock hat seinen eigenen `inbox`).
- `inbox_date` → `payload.content.localized_content.{locale}.{platform}.inbox.expiration_date`.
- `inbox_days`: nicht unterstützt. Konvertieren Sie clientseitig in ein absolutes `expiration_date`.

### Zustellungssteuerung

- `dynamic_content` / `dynamic_content_placeholders` → `dynamic_content_placeholders` auf `segment` oder `transactional`.
- `campaign` → `campaign` auf `segment` oder `transactional`.
- `capping_days` → `frequency_capping.days`.
- `capping_count` → `frequency_capping.count`.
- `send_rate` (int) → `send_rate.value` mit `send_rate.bucket: "1s"`.
- `message_type` (`"marketing"` / `"transactional"`) → `message_type` (`MESSAGE_TYPE_MARKETING` / `MESSAGE_TYPE_TRANSACTIONAL`).

### In v2 nicht unterstützt

- `transactionId`: kein direktes Äquivalent. Verfolgen Sie die Korrelation auf Ihrer Seite.
- `template_bindings`: Liquid-Template-Bindungen sind in v2 nicht verfügbar. Verwenden Sie weiterhin v1, wenn Sie darauf angewiesen sind.

### Plattformspezifische Blöcke

v1 akzeptiert plattformspezifische Parameter auf der obersten Ebene jedes `notifications[*]`-Eintrags (`ios`, `android`, `safari`, `chrome`, …). In v2 werden sie in die locale verschoben:

```
// 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" }
      }
    }
  }
}
```

Feldnamen innerhalb von Plattformblöcken unterscheiden sich an einigen Stellen. Die genauen v2-Namen finden Sie in der [Payload-Referenz](/de/developer/api-reference/messaging-api-v2/payload-reference/).

### Beispiel: Vorher und nachher

**v1 `/createMessage`** (Push an ein Segment):

```json
{
  "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`**:

```json
{
  "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"
  }
}
```

## Von `/createTargetedMessage`

`/createTargetedMessage` wird in den meisten Fällen `transactional` zugeordnet oder `segment`, wenn Sie es ausschließlich als app-übergreifenden `devices_filter` ohne explizite Identifikatoren verwendet haben.

- `devices_filter` → `segment.expression` (seglang) oder `segment.filter_expression` (strukturiert).
- `content` → `payload.content.localized_content.{locale}.{platform}.body`.
- Alle anderen Felder, wie bei `/createMessage` oben.

## Von `/createEmailMessage`

Wechseln Sie zu `Notify` mit `platforms: ["EMAIL"]` und einem `email_payload`-Block. Vollständige Referenz: [E-Mail-Payload-Referenz](/de/developer/api-reference/messaging-api-v2/email-payload-reference/).

- `subject` → `email_payload.subject` (Map mit Locale als Schlüssel. Umschließen Sie Werte für eine einzelne Locale mit `{"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>" }]`).
- Targeting, Zeitplan, Kampagne usw., wie bei `/createMessage`.

## Von `/createSMSMessage`

Wechseln Sie zu `Notify` mit `platforms: ["SMS"]`. Der SMS-Body wird über den konfigurierten SMS-Anbieter der App zugestellt. Fügen Sie den Inhalt in `payload.content.localized_content.{locale}.{platform}.body` in einem beliebigen ausgefüllten Plattformblock ein.

SMS-spezifische Anbieteroptionen (Absender-ID usw.) stammen weiterhin aus der SMS-Konfiguration der App und nicht aus dem Anfrage-Body.

## Von `/createKakaoMessage`

Wechseln Sie zu `Notify` mit `platforms: ["KAKAO"]` und verwenden Sie `payload.content.localized_content.{locale}.kakao`:

- `template_id` → `kakao.template`.
- `content` → `kakao.content`.
- `variables` → `kakao.content_variables` (JSON-stringifiziert).

## Von `/createWhatsAppMessage`

Wechseln Sie zu `Notify` mit `platforms: ["WHATS_APP"]` und verwenden Sie `payload.content.localized_content.{locale}.whatsapp`:

- `content` (Freitext) → `whatsapp.content`. Wird von Meta nur innerhalb des 24-Stunden-Kundenservice-Fensters zugestellt.
- `content_id` → `whatsapp.content_id`. Name einer vorab genehmigten Meta-Vorlage.
- `language` → `whatsapp.language`. Meta-Vorlagen-Locale (z.B. `"en_US"`). Unabhängig vom äußeren `LocalizedContent`-Locale-Schlüssel.
- `content_variables` (Objekt in v1) → `whatsapp.content_variables` (JSON-stringifiziertes Objekt). Beispiel v1 `{"1": "John"}` wird zu v2 `"{\"1\":\"John\"}"`.
- `button_url_variables` (Objekt) → `whatsapp.button_url_variables` (JSON-stringifiziert).
- `header_variables` (Objekt) → `whatsapp.header_variables` (JSON-stringifiziert).
- `preset` → `payload.preset` (generisches Preset auf Payload-Ebene).
- Targeting: Die WhatsApp-Telefonnummer, die in v1 in `devices` ging (z.B. `"whatsapp:+1234567890"`), muss über [`/registerDevice`](/de/developer/api-reference/device-api#registerdevice) für einen Benutzer registriert werden. In v2 zielen Sie auf den resultierenden Benutzer mit `transactional.users.list` (oder die HWID über `transactional.hwids.list`).
- `use_auto_registration`: nicht unterstützt. Registrieren Sie die WhatsApp-Nummer vor dem Senden.

## Von `/createLineMessage`

Wechseln Sie zu `Notify` mit `platforms: ["LINE"]` und verwenden Sie `payload.content.localized_content.{locale}.line`:

- `content` (Klartext) → `line.content`.
- `preset` (LINE-Preset-Code) → `line.template`. Das v2-Feld speichert einen Code, der auf eine im Pushwoosh Control Panel konfigurierte LINE-Vorlage verweist.
- Inline-`template` (v1-Bild-, Karussell- oder Flex-Nachrichtenstrukturen): in v2 nicht direkt unterstützt. Konfigurieren Sie die Rich Message als LINE-Preset im Control Panel vor und verweisen Sie darauf über `line.template`.
- Targeting: Die v1-`devices`-Liste (LINE-Benutzer-IDs, die über das SDK / `/registerDevice` registriert wurden) wird in v2 zu `transactional.users.list` (oder die HWID über `transactional.hwids.list`).

## Unterschiede bei der Antwort

v1 `/createMessage` gibt zurück:

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

v2 `Notify` gibt zurück:

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

Antworten, die nicht den Status 200 haben, folgen dem Standard-gRPC-Gateway-Fehlerformat (`{ "code": ..., "message": ..., "details": [...] }`) anstelle des v1-Paares `status_code` / `status_message`.