Kampagnen
Erstellen, planen und versenden Sie E-Mail-Marketing-Kampagnen mit Tracking und Analysen
Erstellen und verwalten Sie E-Mail-Marketing-Kampagnen. MailLand übernimmt die Empfängerauswahl, den Versand, das Zustellungs-Tracking und die Engagement-Analysen für jede Kampagne.
Kampagnen-Lebenszyklus
Jede Kampagne durchläuft einen definierten Statusablauf:
| Status | Wert | Beschreibung |
|---|---|---|
Draft | 0 | Ausgangszustand: bearbeitbar, noch nicht versendet |
Scheduled | 1 | Für zukünftige Zustellung in der Warteschlange |
Sending | 2 | Wird aktuell an Empfänger versendet |
Sent | 3 | Alle Empfänger verarbeitet |
Paused | 4 | Versand während der Ausführung pausiert |
Cancelled | 5 | Versand abgebrochen |
Failed | 6 | Systemfehler beim Versand |
Erlaubte Übergänge:
Draft→Scheduled(planen) oderSending(sofort senden) oderCancelled(abbrechen)Scheduled→SendingoderCancelled: eine Neuplanung einerScheduled-Kampagne wird nicht unterstütztSending→Sent,Paused,CancelledoderFailedPaused→Sending(fortsetzen)SentoderCancelled→ archiviert
Kampagnentypen
| Typ | Wert | Beschreibung |
|---|---|---|
Regular | 0 | Standard-Einmalkampagne |
Automated | 1 | Durch Automatisierungen ausgelöst |
ABTest | 2 | A/B-Test-Kampagne |
Personalisierung
Kampagnenbetreffzeilen und -inhalte unterstützen {{variable}}-Merge-Tags, die pro Empfänger durch den jeweiligen Datensatz des Abonnenten ersetzt werden.
| Tag | Wert |
|---|---|
{{firstName}} | Vorname des Abonnenten |
{{lastName}} | Nachname des Abonnenten |
{{fullName}} | Vor- und Nachname zusammen |
{{email}} | E-Mail-Adresse des Abonnenten |
{{subscriberId}} | Undurchsichtige Abonnenten-ID |
{{custom_<field>}} | Jedes benutzerdefinierte Feld des Abonnenten, auch verfügbar als {{<field>}} |
<p>Hi {{firstName}}, here's what's new this month.</p>Ein Tag ohne Wert bleibt genau so stehen, wie er geschrieben wurde: {{firstName}} bleibt für einen Abonnenten ohne Vornamen in der zugestellten E-Mail als {{firstName}} bestehen, statt zu einer leeren Lücke zu werden. Schreiben Sie Inhalte, die in beiden Fällen korrekt gelesen werden, z. B. ist Hi there{{firstName}} ungeeignet, aber "Your account" ist sicher. Verwenden Sie eine Ausweich-Anrede, wenn Sie nicht sicher sind, dass jeder Abonnent das Feld hat.
Werte werden je nach Zielbereich escaped: HTML-Inhalt wird HTML-escaped (sodass ein Name mit & oder < Ihr Markup nicht brechen kann), während Betreffzeile und Klartext-Body niemals escaped werden, Ben & Jerry's bleibt genau so.
Die älteren Snake-Case-Schreibweisen ({{first_name}}, {{last_name}}, {{full_name}}, {{subscriber_id}}) funktionieren weiterhin als Aliase.
Kampagne erstellen
Der Workspace muss Business Verified sein, bevor eine Kampagne erstellt oder aktualisiert werden kann: eine frühere, separate Prüfung vor der fromEmail-Prüfung unten. Ist das nicht der Fall, schlägt die Anfrage mit 400 INVALID_REQUEST fehl ("Marketing campaigns require Business Verified status…").
Die fromEmail-Domain muss bereits hinzugefügt und vollständig verifiziert (SPF + DKIM + DMARC) sein, und zwar zum Zeitpunkt der Erstellung und Aktualisierung: sonst wird die Anfrage abgelehnt (400/404). Diese Prüfung erfolgt hier, nicht beim Senden, siehe Sofort senden.
POST https://api.mail.land/v1/marketing/campaigns{
"name": "February Newsletter",
"subject": "What's new in February",
"previewText": "Product updates and tips",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"replyTo": "[email protected]",
"htmlContent": "<html>...</html>",
"textContent": "Plain text version...",
"type": 0,
"mailingListId": "ddv6ou6kz4wbto",
"segmentId": "x4xa3ep1zmqq0b"
}| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
name | string | Ja | Name der Kampagne |
subject | string | Ja | E-Mail-Betreff |
previewText | string | Nein | Vorschautext im Posteingang |
fromName | string | Ja | Anzeigename des Absenders |
fromEmail | string | Ja | E-Mail-Adresse des Absenders |
replyTo | string | Nein | Antwortadresse |
htmlContent | string | Ja | HTML-E-Mail-Text |
textContent | string | Nein | Nur-Text-Fallback |
templateId | string | Nein | Zu verwendende Vorlagen-ID |
type | int | Nein | Kampagnentyp (Standard: 0 Regular) |
mailingListId | string | Nein* | Ziel-Mailingliste |
segmentId | string | Nein* | Zielsegment |
* Geben Sie mailingListId oder segmentId an: eines von beiden ist erforderlich, sofern nicht templateId gesetzt ist.
curl -X POST https://api.mail.land/v1/marketing/campaigns \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "February Newsletter",
"subject": "What'\''s new in February",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"htmlContent": "<html><body><h1>Hello!</h1></body></html>",
"mailingListId": "ddv6ou6kz4wbto"
}'Antwort
{
"id": "uivozyvucowj9w",
"name": "February Newsletter",
"subject": "What's new in February",
"previewText": "Product updates and tips",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"status": "draft",
"statusName": "Draft",
"type": 0,
"typeName": "Regular",
"mailingListId": "ddv6ou6kz4wbto",
"mailingListName": "Main Newsletter",
"segmentId": null,
"segmentName": null,
"createdAt": "2026-02-17T12:00:00Z",
"updatedAt": "2026-02-17T12:00:00Z"
}Kampagnen auflisten
GET https://api.mail.land/v1/marketing/campaigns| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
cursor | string | - | Opaker Cursor aus dem nextCursor der vorherigen Seite. Für die erste Seite weglassen. |
limit | int | 20 | Einträge pro Seite (max. 100) |
search | string | - | Nach Name suchen |
status | int | - | Nach CampaignStatus filtern |
type | int | - | Nach CampaignType filtern |
mailingListId | string | - | Nach Mailingliste filtern |
sortBy | string | - | Sortierfeld |
sortDesc | bool | false | Absteigende Sortierung |
includeArchived | bool | false | Archivierte Kampagnen einschließen |
curl "https://api.mail.land/v1/marketing/campaigns?limit=20&status=3" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{
"id": "uivozyvucowj9w",
"name": "February Newsletter",
"subject": "What's new in February",
"status": "sent",
"statusName": "Sent",
"type": 0,
"typeName": "Regular",
"mailingListId": "ddv6ou6kz4wbto",
"mailingListName": "Main Newsletter",
"totalRecipients": 5000,
"totalSent": 4980,
"totalDelivered": 4900,
"totalOpened": 1520,
"totalClicked": 195,
"totalBounced": 45,
"totalUnsubscribed": 12,
"sentAt": "2026-02-15T10:00:00Z",
"completedAt": "2026-02-15T10:35:00Z",
"createdAt": "2026-02-14T08:00:00Z"
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}Kampagnendetails abrufen
GET https://api.mail.land/v1/marketing/campaigns/{id}Gibt das vollständige CampaignDetailDto zurück, einschließlich HTML-Inhalt, aller Statistiken und berechneter Engagement-Raten:
curl https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"id": "uivozyvucowj9w",
"name": "February Newsletter",
"subject": "What's new in February",
"previewText": "Product updates and tips",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"replyTo": "[email protected]",
"status": "sent",
"statusName": "Sent",
"type": 0,
"typeName": "Regular",
"htmlContent": "<html>...</html>",
"textContent": "Plain text...",
"mailingListId": "ddv6ou6kz4wbto",
"mailingListName": "Main Newsletter",
"totalRecipients": 5000,
"totalSent": 4980,
"totalDelivered": 4900,
"totalOpened": 1520,
"totalClicked": 195,
"totalBounced": 45,
"totalUnsubscribed": 12,
"totalComplaints": 2,
"deliveryRate": 98.39,
"openRate": 31.02,
"clickRate": 3.98,
"clickToOpenRate": 12.83,
"bounceRate": 0.9,
"unsubscribeRate": 0.24,
"openTrackingEnabled": true,
"clickTrackingEnabled": true,
"sentAt": "2026-02-15T10:00:00Z",
"completedAt": "2026-02-15T10:35:00Z",
"createdAt": "2026-02-14T08:00:00Z",
"updatedAt": "2026-02-15T10:35:00Z"
}Engagement-Raten
| Rate | Formel |
|---|---|
deliveryRate | totalDelivered / totalSent * 100 |
openRate | totalOpened / totalDelivered * 100 |
clickRate | totalClicked / totalDelivered * 100 |
clickToOpenRate | totalClicked / totalOpened * 100 |
bounceRate | totalBounced / totalSent * 100 |
unsubscribeRate | totalUnsubscribed / totalDelivered * 100 |
Die Raten werden auf dem Server aus den Rohzählern berechnet (Öffnungen und Klicks sind je Empfänger eindeutig). deliveryRate und bounceRate beziehen sich auf Gesendetes; openRate, clickRate und unsubscribeRate auf Zugestelltes; clickToOpenRate (CTOR) ist Klicker im Verhältnis zu Öffnern und eine eigene Kennzahl neben clickRate. Eine Rate ist ein Prozentwert ohne Obergrenze (clickToOpenRate kann 100 überschreiten) und ist null, nie 0, wenn sie nicht verfügbar ist: der Nenner ist 0 oder das nötige Tracking ist im Konto ausgeschaltet (openTrackingEnabled / clickTrackingEnabled zeigen die aktuelle Einstellung). Um Kampagnen zusammenzufassen, addieren Sie die Zähler und teilen einmal; mitteln Sie keine Prozentwerte. Dieselben Felder liefert auch die Liste je Kampagne.
Kampagne aktualisieren
PUT https://api.mail.land/v1/marketing/campaigns/{id}Nur Kampagnen im Status Draft oder Scheduled können aktualisiert werden. Der Anfrage-Body entspricht dem der Erstellungsanfrage, außer type, das nicht geändert werden kann.
| Status | Code | Beschreibung |
|---|---|---|
200 | - | Kampagne aktualisiert |
400 | INVALID_REQUEST | Nur Entwurfskampagnen können bearbeitet werden |
404 | RESOURCE_NOT_FOUND | Kampagne nicht gefunden |
curl -X PUT https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "February Newsletter (Updated)",
"subject": "What'\''s new in February - updated",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"htmlContent": "<html><body><h1>Updated!</h1></body></html>",
"mailingListId": "ddv6ou6kz4wbto"
}'Kampagne planen
POST https://api.mail.land/v1/marketing/campaigns/{id}/schedule{
"scheduledAt": "2026-02-20T14:00:00Z"
}Der scheduledAt-Zeitpunkt muss in der Zukunft liegen. Der Kampagnenstatus wechselt zu Scheduled und der CampaignWorker verarbeitet sie zum geplanten Zeitpunkt.
Die Planung ist nur aus dem Status Draft möglich: eine bereits Scheduled-Kampagne kann über diesen Endpunkt nicht neu geplant werden.
| Status | Code | Beschreibung |
|---|---|---|
200 | - | Kampagne geplant |
400 | VALIDATION_FAILED | Der geplante Zeitpunkt muss in der Zukunft liegen |
404 | RESOURCE_NOT_FOUND | Kampagne nicht gefunden oder kann nicht geplant werden |
403 | MARKETING_NOT_YET_ALLOWED | Marketing ist für das Konto noch nicht freigeschaltet (siehe Fehlercodes); /send gibt ihn ebenfalls zurück |
403 | MARKETING_SUSPENDED | Marketing ist plattformweit nicht verfügbar; /send gibt ihn ebenfalls zurück |
422 | CAMPAIGN_LINK_BLOCKED | Ein Link in der Kampagne zeigt auf ein als unsicher eingestuftes Ziel; /send gibt ihn ebenfalls zurück. Es wird nichts geplant oder gesendet |
curl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/schedule \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "scheduledAt": "2026-02-20T14:00:00Z" }'Sofort senden
POST https://api.mail.land/v1/marketing/campaigns/{id}/sendSendet die Kampagne sofort. Der Kampagnenstatus wechselt zu Sending und der CampaignWorker beginnt mit der Verarbeitung der Empfänger.
/send selbst prüft die Domain-Verifizierung nicht: diese Prüfung erfolgt bei der Erstellung/Aktualisierung (siehe Kampagne erstellen). /send liefert 422 CAMPAIGN_NO_ELIGIBLE_RECIPIENTS, wenn niemand in der Zielliste/dem Zielsegment für den Empfang der Kampagne infrage kommt (z. B. alle unterdrückt oder abgemeldet).
curl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/send \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Pausieren und Fortsetzen
Eine laufende Kampagne pausieren:
POST https://api.mail.land/v1/marketing/campaigns/{id}/pausecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/pause \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Eine pausierte Kampagne fortsetzen:
POST https://api.mail.land/v1/marketing/campaigns/{id}/resumecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/resume \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Das Pausieren stoppt den CampaignWorker bei der Verarbeitung verbleibender Empfänger. Bereits versendete E-Mails sind nicht betroffen. Beim Fortsetzen wird ab dem Unterbrechungspunkt weitergemacht.
Kampagne abbrechen
POST https://api.mail.land/v1/marketing/campaigns/{id}/cancelBricht eine Kampagne im Status Draft, Scheduled oder Sending ab. Bereits versendete E-Mails werden nicht zurückgerufen.
curl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/cancel \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Kampagne duplizieren
POST https://api.mail.land/v1/marketing/campaigns/{id}/duplicate?name=Copy%20of%20NewsletterErstellt eine neue Draft-Kampagne mit allen Einstellungen aus dem Original. Der name-Abfrageparameter ist optional.
curl -X POST "https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/duplicate?name=Copy%20of%20Newsletter" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Archivieren und Dearchivieren
Eine Sent- oder Cancelled-Kampagne archivieren:
POST https://api.mail.land/v1/marketing/campaigns/{id}/archivecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/archive \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Eine archivierte Kampagne dearchivieren:
POST https://api.mail.land/v1/marketing/campaigns/{id}/unarchivecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/unarchive \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Archivierte Kampagnen werden in der Standard-Listenansicht ausgeblendet, es sei denn, includeArchived=true wird übergeben.
Kampagnenempfänger
Paginierte Empfänger mit Zustellungsstatus für eine Kampagne abrufen:
GET https://api.mail.land/v1/marketing/campaigns/{id}/recipients| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
cursor | string | - | Opaker Cursor aus dem nextCursor der vorherigen Seite. Für die erste Seite weglassen. |
limit | int | 20 | Einträge pro Seite (max. 100) |
status | string | - | Nach Empfängerstatus filtern |
search | string | - | Nach E-Mail suchen |
curl "https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/recipients?limit=20" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{
"email": "[email protected]",
"status": "Opened",
"sentAt": "2026-02-15T10:00:30Z",
"deliveredAt": "2026-02-15T10:00:32Z",
"openedAt": "2026-02-15T11:15:00Z",
"clickedAt": "2026-02-15T11:16:30Z",
"bouncedAt": null,
"complainedAt": null,
"unsubscribedAt": null,
"openCount": 2,
"clickCount": 1,
"bounceReason": null
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}Empfänger-Status
| Status | Wert | Beschreibung |
|---|---|---|
Pending | 0 | In der Warteschlange, noch nicht versendet |
Sent | 1 | Vom MTA akzeptiert |
Delivered | 2 | An Empfänger zugestellt |
Opened | 3 | Empfänger hat geöffnet |
Clicked | 4 | Empfänger hat einen Link angeklickt |
Bounced | 5 | Hartes Bounce |
Unsubscribed | 6 | Empfänger hat sich abgemeldet |
Complained | 7 | Spam-Beschwerde |
Failed | 8 | Zustellung fehlgeschlagen |
openedAt/openCount und clickedAt/clickCount enthalten maschinelle Aktivität, Apple Mail Privacy Protection Prefetch und Sicherheits-Link-Scanner, die MailLand heute nicht herausfiltert. Behandeln Sie aus Öffnungen/Klicks abgeleitete Raten als Obergrenze, nicht als präzise Kennzahl menschlichen Engagements.
Kampagne löschen
DELETE https://api.mail.land/v1/marketing/campaigns/{id}Löscht eine Kampagne und ihre Empfängerdaten dauerhaft. Nur Kampagnen im Status Draft oder Scheduled können gelöscht werden; das Löschen jedes anderen Status liefert 404: archivieren Sie eine gesendete Kampagne stattdessen.
curl -X DELETE https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Fehlerantworten
| Status | Code | Beschreibung |
|---|---|---|
400 | VALIDATION_FAILED | Pflichtfelder fehlen |
400 | INVALID_REQUEST | Nur Entwurfskampagnen können bearbeitet werden |
403 | FORBIDDEN | Unzureichende Berechtigungen |
404 | RESOURCE_NOT_FOUND | Kampagne nicht gefunden |
Nächste Schritte
- Abonnenten: verwalten Sie Ihre Abonnentenkontakte
- Listen: organisieren Sie Abonnenten in Mailinglisten
- Segmente: richten Sie Kampagnen mit dynamischen Segmenten aus
- Automatisierungen: richten Sie triggerbasierte E-Mail-Sequenzen ein