> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Kampagne End-to-End senden: Entwurf, Zielgruppe, Dry-Run, Start, Analyse

> Begleiten Sie eine Kampagne vom Entwurf über den Start bis zur Messung — Zielgruppe wählen, Empfänger prüfen, den Pre-Flight-Dry-Run ausführen, als Blast oder Drip starten und Statistiken, Holdout-Lift und ROI lesen.

## Sprachhinweis

Diese deutsche Variante ist eine gekürzte Übersetzung: Die Abschnitte „4. Personalization and locale", „8. Subscribe to campaign webhooks" und „Worked example: retail promo, draft to analytics" existieren nur in der englischen Fassung: [/en/guides/campaign-end-to-end](https://docs.orbit.devotel.io/en/guides/campaign-end-to-end). Code-Blöcke, Endpoint-Pfade, API-Feldnamen und Fehlercodes bleiben englisch.

# Kampagne End-to-End senden

Dieses Guide führt durch den gesamten Kampagnen-Lebenszyklus über die API: Entwurf anlegen, Zielgruppe verknüpfen, Personalisierung prüfen, den Pre-Flight-Dry-Run ausführen, starten und das Ergebnis messen. Einmal durchgegangen, funktioniert dieselbe Reihenfolge für jeden Kanal — SMS, WhatsApp, E-Mail, RCS, Voice, Push.

## 1. Voraussetzungen

* **Ein API-Key mit Scope `campaigns:write`.** Alle Lesezugriffe unten (Audience-Preview, Dry-Run, Statistiken) akzeptieren auch `campaigns:read`, aber Startaktionen benötigen Write. Keys erstellen oder bearbeiten Sie im Dashboard unter Settings → API keys.
* **Node SDK (optional).** `npm install @devotel-orbit/node`, wenn Sie die SDK-Tabs cURL vorziehen.
* **Eine sendefähige Identität für Ihren Kanal.** Für SMS/MMS eine Nummer oder ein Sender-Pool mit den richtigen Registrierungen (US A2P benötigt [10DLC](https://docs.orbit.devotel.io/guides/10dlc-registration.md)); für WhatsApp eine verbundene WABA; für E-Mail eine verifizierte Absenderdomain.
* **Eine legitimierte Zielgruppen-Quelle.** Eine Kontaktliste, ein Live-Segment, eine CSV mit Empfängeradressen, eine externe CRM-Zielgruppe (HubSpot-Liste / Salesforce-Report) oder eine handverlesene Menge von Kontakt-IDs. Zielgruppen müssen aus Empfängern mit Opt-in bestehen — Suppression und Abmeldungen werden zur Sendezeit durchgesetzt, nicht dem Absender überlassen.

## 2. Kampagnen-Entwurf anlegen

Legen Sie die Kampagne mit Kanal, Zielgruppe und `message_template` an. Das Template ist beim Anlegen optional — ein Entwurf ohne Template kann nicht starten — aber es vorab zu liefern hält den Entwurf vollständig.

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Retail promo — summer sale",
    "type": "blast",
    "channel": "sms",
    "audience_type": "list",
    "audience_id": "list_summerVIPs",
    "message_template": "Hi {{first_name}}, early access to our summer sale starts now: 25% off through Sunday. Reply STOP to opt out.",
    "send_time_optimization": "fixed"
  }'
```

```typescript Node.js (TypeScript) theme={null}
import { Orbit } from "@devotel-orbit/node";

const orbit = new Orbit({ apiKey: process.env.ORBIT_API_KEY });

const campaign = await orbit.campaigns.create({
  name: "Retail promo — summer sale",
  channel: "sms",
  message_template:
    "Hi {{first_name}}, early access to our summer sale starts now: 25% off through Sunday. Reply STOP to opt out.",
});
```

Wichtige Felder beim Anlegen:

| Feld | Hinweise |
| - | - |
| `type` | `blast` (eine geplante Sendung), `drip` (mehrstufige Sequenz), `journey` (ereignisgesteuert) oder `ad`. |
| `audience_type` | `all`, `list`, `segment`, `csv` oder `manual` (handverlesene Kontakt-IDs). |
| `audience_id` | Erforderlich, wenn `audience_type` `list` oder `segment` ist. |
| `audience_source` | Optionale CRM-Kennung (`hubspot_list`, `salesforce_report`, …), die zur Sendezeit das List/Segment-Paar überschreibt. |
| `message_template` | Bis zu 100.000 Zeichen; E-Mail-Texte passen bequem hinein. Personalisierungstoken nutzen die Form `{{token}}`. |
| `subject` | Betreff nur für E-Mail. Wird bei anderen Kanälen ignoriert. |
| `send_time_optimization` | `fixed` (ein fester Batch-Zeitpunkt) oder `recipient-optimal` (beste Zeit je Kontakt, siehe Schritt 6). |
| `throttle_rate` | Sendelimit in Nachrichten/Sekunde, 0–1000. Fehlend oder 0 = Standard-Pacing der Plattform. |
| `scheduled_at` | ISO-Zeitstempel für den Start, später änderbar. Muss in der Zukunft liegen. |
| `credit_cap_usd_cents` | Harte Ausgabengrenze; die Kampagne pausiert automatisch, sobald sie erreicht wird. |

Die Antwort liefert die Kampagne im Status `draft`. Nichts wird gesendet, bis Schritt 6 sie explizit startet.

## 3. Zielgruppe verknüpfen und prüfen

**Liste oder Segment.** Übergeben Sie `audience_type: "list" | "segment"` mit einer `audience_id` oder einer CRM-`audience_source`-Kennung. Segmente werden zur Sendezeit live ausgewertet — ein wachsendes Segment funktioniert also weiter.

**CSV-Empfänger.** Für eine einmalige Liste POSTen Sie die Adressen direkt in das Array `variables.csv_recipients` der Kampagne (E.164 für Telefonkanäle).

**Manuelle Auswahl.** `audience_type: "manual"` mit `variables.manual_contact_ids` adressiert bestimmte Kontakt-IDs — dieselbe Eligibility-Logik wie bei einer Liste.

Zählen Sie vor dem Start immer, worauf sich die Zielgruppe auflöst. `POST /api/v1/campaigns/audience/preview` akzeptiert dieselbe Audience-Form wie die Kampagne und liefert `matching_count` plus eine Stichprobe von 10 Kontakten:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/audience/preview" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audience_type": "list",
    "audience_id": "list_summerVIPs",
    "channel": "sms"
  }'
```

Übergeben Sie `channel`, liefert die Antwort zusätzlich eine Nettoprojektion: Brutto-Treffer minus Suppression-Liste, minus kanalweite Opt-outs, minus Kontakte ohne zustellbare Adresse für diesen Kanal. Kommt `matching_count` als 0 zurück, beheben Sie die Zielgruppe, bevor Sie weitergehen — hier iterieren Sie.

## 5. Pre-Flight: Dry-Run ausführen

POSTen Sie vor dem Start den Dry-Run. Er ist read-only — er verändert keinen Zustand, belastet das Wallet nicht und stellt keine Jobs in die Warteschlange.

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/campaigns/cmp_abc123/dry-run" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

Der Report bündelt die zentralen Buckets:

* `audience.total_in_audience` — brutto passende Empfänger.
* `audience.suppressed` / `opted_out` / `unreachable` — die Kohorten der Nettoprojektion.
* `audience.deliverable` — die exakte Nettozahl, die der Start versucht.
* `cost.unit_price_cents` / `cost.total_cents` — über denselben Resolver bepreist wie der Sendepfad.
* `cost.balance_cents` / `cost.sufficient` — Wallet-Prüfung; ein grüner Dry-Run bedeutet eine grüne Balance-Gate beim Start.
* `quiet_hours.skipped_estimate` und `quiet_hours.window` — projizierter Skip-Anteil durch recipient-local Quiet Hours.
* `warnings[]` — nicht blockierende Hinweise, getrennt von harten Fehlern dargestellt.

Ein gesunder Dry-Run mit `warnings: []` und `cost.sufficient: true` gibt den Start frei.

## 6. Starten und Sendeform wählen

Starten Sie mit `POST /api/v1/campaigns/cmp_abc123/send` (oder `scheduled_at` für einen späteren Batch). Vier Sendeformen stehen zur Wahl:

**Blast.** Ein Batch zu einem Zeitpunkt — die einfachste Form; die gesamte zustellbare Zielgruppe geht in einem Durchlauf mit `throttle_rate`-Pacing hinaus.

**Drip-Sequenz.** `type: "drip"` mit einem `steps`-Array (bis zu 50 Schritte). Jeder Schritt hat eigenen Kanal, Verzögerung und optional eine Lesebedingung.

**Journey.** `type: "journey"` — ereignisgesteuerte Aufnahme mit Analytics je Knoten.

**Channel-Fallback-Leiter.** Für Omnichannel-Kampagnen ist das `channels`-Array eine geordnete Kette; jeder Eintrag außer dem letzten trägt einen `fallback_on`-Trigger (`failed`, `no_delivery` oder `no_engagement`) und ein `fallback_after_seconds`-Fenster.

Diese Pacing-Regler gelten immer:

* **Throttle.** `throttle_rate` (Nachrichten/Sekunde) begrenzt das Sendetempo — Standard ist 50 msg/s.
* **Smart Send.** `send_time_optimization: "recipient-optimal"` plant jeden Empfänger in sein nächstes Best-Time-Fenster und verteilt die Zustellung über die folgenden 24 Stunden.
* **Sendewindow.** `send_window: { start_local_hour, end_local_hour }` stellt Empfänger zurück, deren Ortszeit außerhalb des Fensters liegt.

## 7. Beobachten und messen

**Live-Statistiken.** `GET /campaigns/:id/stats` liefert Summen für sent, delivered, failed, opened, clicked, replied.

**Holdout-Lift.** Hat die Kampagne einen Holdout gesetzt (`campaign_holdout_percent` in `variables`), vergleicht `GET /campaigns/:id/holdout-lift` die Treatment-Kohorte mit der Kontrolle und liefert eine Conversion-Delta mit Konfidenzintervall — so sehen Sie, ob die Nachricht besser war als nichts zu senden.

**ROI / ROAS.** `GET /campaigns/:id/roas` liefert attribuierten Umsatz, Klick-Funnel und Holdout-inkrementellen Umsatz; `GET /campaigns/:id/cost` und `/campaigns/:id/export` dienen der Abstimmung der Ausgaben.

## 9. Fehlerbehebung

* **Zielgruppe löst sich auf null auf.** Führen Sie den Audience-Preview mit übergebenem `channel` erneut aus; die Nettoprojektion nennt die Kohorte, die sie geleert hat.
* **Dry-Run zeigt rote Warnungen.** `warnings[]`-Einträge sind explizit — „no provider registered" bedeutet, der Kanal hat keine konfigurierte sendende Identität; „insufficient balance" bedeutet `cost.sufficient: false`.
* **Start liefert 402 oder eine Pending-Approval-Antwort.** Balance-Prüfung fehlgeschlagen oder der Approval-Workflow ist aktiv — Wallet aufladen oder auf die Freigabe warten.
* **Journey-Kampagne steckt in paused.** Eine Kampagne pausiert automatisch bei `credit_cap_usd_cents` oder einer defekten Drip-Bedingung. Blocker beseitigen, dann `POST /campaigns/:id/resume`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.