Senden Sie eine ausgehende E-Mail pro Empfänger von einer FORM- oder CONTACT_FORM-Integration unter Verwendung des outboundMail-SMTP dieser Integration. Der Aufruf erfolgt Server-zu-Server mit X-API-Key und der Berechtigung ``transactional.send``.
Dies ist kein zustandsloses SMTP-Relay. Mailoo erstellt einen vollständigen Versand-Lifecycle innerhalb der Integration: TransactionalSend, Message (OUTBOUND), optionaler Subscriber-Sync, Open/Click-Tracking und optionale Delivery-Webhooks. Siehe outbound-smtp{.interpreted-text role="doc"} für die Abgrenzung zur Offenlegung von SMTP-Zugangsdaten an Integratoren.
Verwandt: SMTP-Ebene --- outbound-smtp{.interpreted-text role="doc"}; Abmelde-Tokens --- website-forms{.interpreted-text role="doc"}; OpenAPI --- https://api.mailoo.app/docs/v1.
Architektur
- Auslöser, kein Relay: Ihr Backend ruft Mailoo auf; Mailoo rendert die Nachricht, speichert Datensätze und versendet über ``integration.config.outboundMail`` (dasselbe SMTP wie Dashboard-Antworten und Willkommensmails).
- Zugangsdaten: Verwenden Sie ``X-API-Key`` mit ``transactional.send`` (oder FULL) ausschließlich von Ihrem Server oder BFF --- niemals in Browser-Bundles.
- Idempotenz: Jede Anfrage erfordert ``idempotencyKey`` (max. 256 Zeichen, eindeutig pro Integration). Erster Erfolg gibt 201 zurück; Wiederholungen geben 200 mit
idempotentReplay: truezurück. - Abonnenten: Mailoo erstellt oder aktualisiert einen
Subscriberfür die Empfänger-E-Mail. WennunsubscribedAtgesetzt ist, wird der Versand übersprungen (409, StatusSKIPPED_UNSUBSCRIBED). - Zustellungsereignisse: Optionale ausgehende Webhooks (
delivered,opened,clicked,unsubscribed,bounced) mit HMAC-Signierung und Wiederholungen --- siehe Delivery-Webhooks unten.
Versand-Endpunkt
``POST {baseUrl}/api/v1/webhooks/transactional/{projectUid}/{integrationId}/send``
Header: Content-Type: application/json, X-API-Key (Berechtigung ``transactional.send`` oder FULL)
Body (JSON):
- ``idempotencyKey`` (erforderlich) --- stabiler Schlüssel für diesen logischen Versand (z. B.
daily-2026-06-20-user123) - ``to`` (erforderlich) --- Empfänger-E-Mail
- ``name`` (optional) --- Anzeigename; wird für
{{User.name}}/{{firstName}}verwendet - ``templateId`` (optional) --- Kampagnen-ID (Dashboard-Kampagne dieser Integration); verwenden Sie entweder
templateIdoder Inline-subject+text/html - ``vars`` (optional) --- Objekt mit String-/Zahlen-/Boolean-Mustache-Variablen (siehe unten)
- ``subject``, ``text``, ``html`` (optional) --- Inline-Inhalt ohne
templateId; Subject und mindestenstextoderhtmlsind für Inline-Versand erforderlich
Antworten:
- 201 --- E-Mail gesendet (
status: SENT,idempotentReplay: false) - 200 --- idempotente Wiederholung eines früheren Versands
- 409 --- Empfänger abgemeldet (
status: SKIPPED_UNSUBSCRIBED) - 502 --- SMTP-Versand fehlgeschlagen (
status: FAILED;MessageundBOUNCED-Delivery-Webhook können trotzdem aufgezeichnet werden) - 400 --- Validierungsfehler
- 403 --- API-Schlüssel ohne ``transactional.send``
- 404 --- Projekt/Integration nicht gefunden oder nicht FORM/CONTACT_FORM
Beispiel (Inline):
curl -X POST "https://api.mailoo.app/api/v1/webhooks/transactional/{projectUid}/{integrationId}/send" \
-H "Content-Type: application/json" \
-H "X-API-Key: mai_live_..." \
-d '{
"idempotencyKey": "daily-2026-06-20-user1",
"to": "user@example.com",
"name": "Jane Doe",
"subject": "Hi {{firstName}}",
"html": "<p>{{affirmationText}} <a href=\"{{writeUrl}}\">Write</a></p><p><a href=\"{{unsubLink}}\">Unsubscribe</a></p>",
"vars": {
"affirmationText": "You are enough.",
"writeUrl": "https://app.example.com/write"
}
}'
Beispielantwort (201):
{
"success": true,
"data": {
"sendId": "clx...",
"messageId": "clx...",
"status": "SENT",
"idempotentReplay": false
}
}
Mustache-Variablen
Vorlagen (Kampagnen-templateId oder Inline-subject/text/html) werden vor dem SMTP-Versand mit Mustache gerendert.
Eingebauter Kontext:
- ``User.email``, ``User.name`` --- aus
to/name - ``firstName`` --- aus
vars.firstNameoder erstes Token vonname - ``unsubLink`` --- Ein-Klick-Abmelde-URL (integrations-eigenes Signier-Secret + API-``MAILOO_PUBLIC_APP_URL``)
- ``affirmationText``, ``writeUrl``, ``streak`` --- aus
vars, wenn angegeben (üblich für Retention-/Nudge-Flows)
Zusätzliche String-/Zahlen-/Boolean-Schlüssel in vars werden in den Kontext eingefügt.
Open- und Click-Tracking
Wenn der HTML-Body nicht leer ist, fügt Mailoo ein:
- Ein 1×1-Open-Tracking-Pixel
- Umgeschriebene
https://- (und//-)Links über Click-Tracking-Redirects
Öffentliche Routen (kein API-Schlüssel):
- ``GET /api/v1/public/transactional/open/{trackingToken}`` --- gibt transparentes GIF zurück; zeichnet erstes Öffnen auf
- ``GET /api/v1/public/transactional/click/{trackingToken}?u={urlencodedTarget}`` --- zeichnet Klick auf, 302-Redirect zum Ziel
Setzen Sie ``MAILOO_PUBLIC_API_URL`` auf dem API-Host, damit Pixel- und Klick-URLs auf Ihre öffentliche API zeigen. Setzen Sie ``MAILOO_PUBLIC_APP_URL``, wenn Abmelde- und App-Links auf den Dashboard-Origin zeigen müssen.
Delivery-Webhooks
Wenn konfiguriert, sendet Mailoo JSON-Ereignisse per POST an Ihren Benachrichtigungs-Endpunkt.
Konfiguration (pro Integration):
integration.config.deliveryWebhook.url und .secret --- im Dashboard (Delivery webhooks auf dem Setup-Reiter der Integration) oder über PATCH …/integrations/{id} mit deliveryWebhook setzen.
Ereignisse: delivered (nach erfolgreichem SMTP), opened, clicked, unsubscribed (nach Abmelde-Webhook), bounced (SMTP-Fehler).
Nutzlastform (JSON):
{
"event": "delivered",
"integrationId": "...",
"messageId": "...",
"idempotencyKey": "...",
"recipientEmail": "user@example.com",
"timestamp": "2026-06-20T12:00:00.000Z",
"metadata": {}
}
Signierung: Header ``X-Mailoo-Signature: t={unixSeconds},v1={hex}``, wobei v1 HMAC-SHA256 von "{timestamp}.{rawBody}" mit dem Webhook-Secret ist. Header ``X-Mailoo-Event`` wiederholt den Enum-Namen (z. B. DELIVERED).
Wiederholungen: Outbox-Worker (10-Sekunden-Intervall im API-Prozess) wiederholt fehlgeschlagene Zustellungen bis zu 8 Versuche mit exponentiellem Backoff (max. 5 Minuten). Setzen Sie ``DISABLE_DELIVERY_WEBHOOK_WORKER=1`` nur für Tests oder wenn Sie einen separaten Prozessor betreiben.
Voraussetzungen
- FORM- oder CONTACT_FORM-Integration mit ACTIVE-Status
- ``outboundMail`` konfiguriert (Dashboard → Connection & settings → Outbound email)
- ``MAIL_SMTP_ENCRYPTION_KEY`` auf der API, wenn SMTP-Passwort oder Abmelde-Secret verschlüsselt gespeichert wird
- RESTRICTED- oder FULL-API-Schlüssel mit ``transactional.send``
Abmelde-Signierung
Jede FORM-/CONTACT_FORM-Integration speichert ein verschlüsseltes Abmelde-HMAC-Secret in integration.config. Mailoo generiert {{unsubLink}} automatisch in Transaktionsvorlagen. Eigentümer können das Secret im Dashboard rotieren (macht Links in bereits gesendeten E-Mails ungültig). Externe Backends, die eigene Links signieren, benötigen den rotierten Klartext einmalig, oder sollten stattdessen ``POST /api/v1/webhooks/unsubscribe`` mit einem API-Schlüssel aufrufen.