Zum Inhalt

Webhooks

Webhooks benachrichtigen Ihre Anwendung in Echtzeit, wenn Ereignisse in SubscribeFlow auftreten. Anstatt die API abzufragen, registrieren Sie eine Endpoint-URL und SubscribeFlow sendet einen HTTP-POST-Request für jedes passende Ereignis.

Webhook-Endpoint erstellen

webhook = await client.webhooks.create(
    url="https://your-app.com/webhooks/subscribeflow",
    events=["subscriber.created", "tag.subscribed"],
    description="Haupt-Webhook-Endpoint",
)
# Signing Secret sicher speichern!
print(f"Secret: {webhook.secret}")
const webhook = await client.webhooks.create({
  url: 'https://your-app.com/webhooks/subscribeflow',
  events: ['subscriber.created', 'tag.subscribed'],
  description: 'Haupt-Webhook-Endpoint',
});

// Signing Secret sicher speichern!
console.log('Secret:', webhook.signing_secret);
curl -X POST https://api.subscribeflow.net/api/v1/webhooks \
  -H "X-API-Key: sf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/subscribeflow",
    "events": ["subscriber.created", "tag.subscribed"],
    "description": "Haupt-Webhook-Endpoint"
  }'

Warning

Das Signing Secret wird nur bei der Erstellung zurückgegeben. Speichern Sie es sofort in einem Secret Manager oder einer Umgebungsvariable.

Ereignistypen

Ereignis Beschreibung
subscriber.created Ein neuer Subscriber wurde hinzugefügt
subscriber.updated Subscriber-Daten (E-Mail, Status, Metadaten) wurden geändert
subscriber.deleted Ein Subscriber wurde dauerhaft gelöscht
tag.subscribed Ein Subscriber wurde einem Tag hinzugefügt
tag.unsubscribed Ein Subscriber wurde von einem Tag entfernt
subscriber.note_added Eine Notiz wurde zu einem Subscriber hinzugefügt

Jede Webhook-Zustellung enthält ein JSON-Payload mit dem Ereignistyp, einem Zeitstempel und dem vollständigen Ressourcen-Objekt.

Signatur-Verifizierung

Jede Zustellung enthält einen X-SubscribeFlow-Signature-Header mit einer HMAC-SHA256-Signatur des Request-Bodys. Verifizieren Sie diese Signatur immer, bevor Sie das Payload verarbeiten.

import hmac
import hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

# In Ihrem Webhook-Handler (FastAPI-Beispiel):
from fastapi import Request, HTTPException

@app.post("/webhooks/subscribeflow")
async def handle_webhook(request: Request):
    body = await request.body()
    signature = request.headers.get("X-SubscribeFlow-Signature", "")

    if not verify_signature(body, signature, WEBHOOK_SECRET):
        raise HTTPException(status_code=401, detail="Ungueltige Signatur")

    event = await request.json()
    print(f"Empfangen: {event['event_type']}")
import crypto from 'node:crypto';

function verifySignature(
  payload: string,
  signature: string,
  secret: string,
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return signature === `sha256=${expected}`;
}

// In Ihrem Webhook-Handler (Express-Beispiel):
import express from 'express';

const app = express();
app.use(express.raw({ type: 'application/json' }));

app.post('/webhooks/subscribeflow', (req, res) => {
  const signature = req.headers['x-subscribeflow-signature'] as string;
  const body = req.body.toString();

  if (!verifySignature(body, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Ungueltige Signatur');
  }

  const event = JSON.parse(body);
  console.log('Empfangen:', event.event_type);
  res.sendStatus(200);
});
# Signatur manuell mit openssl verifizieren:
PAYLOAD='{"event_type":"subscriber.created","data":{...}}'
SECRET="whsec_..."

EXPECTED=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
echo "sha256=$EXPECTED"

Warning

Verwenden Sie immer eine zeitkonstante Vergleichsfunktion (wie hmac.compare_digest in Python oder crypto.timingSafeEqual in Node.js), um Timing-Angriffe zu verhindern.

Zustellungs-Monitoring

Zustellungen auflisten

deliveries = await client.webhooks.list_deliveries("webhook-id")
for d in deliveries:
    print(f"{d.event_type}: {d.status}")
const deliveries = await client.webhooks.listDeliveries('webhook-id');
for (const d of deliveries.items) {
  console.log(`${d.event_type}: ${d.status}`);
}
curl https://api.subscribeflow.net/api/v1/webhooks/WEBHOOK_ID/deliveries \
  -H "X-API-Key: sf_live_..."

Fehlgeschlagene Zustellung wiederholen

await client.webhooks.retry_delivery("webhook-id", "delivery-id")
await client.webhooks.retryDelivery('webhook-id', 'delivery-id');
curl -X POST \
  https://api.subscribeflow.net/api/v1/webhooks/WEBHOOK_ID/deliveries/DELIVERY_ID/retry \
  -H "X-API-Key: sf_live_..."

Webhook testen

Senden Sie ein Testereignis, um zu prüfen, ob Ihr Endpoint erreichbar und korrekt konfiguriert ist.

result = await client.webhooks.test("webhook-id")
if result.success:
    print(f"Funktioniert! Antwortzeit: {result.response_time_ms}ms")
else:
    print(f"Fehlgeschlagen: {result.error}")
const result = await client.webhooks.test('webhook-id', 'subscriber.created');
if (result.success) {
  console.log(`Funktioniert! Antwortzeit: ${result.response_time_ms}ms`);
} else {
  console.log('Fehlgeschlagen:', result.error);
}
curl -X POST https://api.subscribeflow.net/api/v1/webhooks/WEBHOOK_ID/test \
  -H "X-API-Key: sf_live_..."

Hands-On: Auf Subscriber-Ereignisse reagieren

Richten Sie einen Webhook ein, der jeden neuen Subscriber in Ihrer Anwendung protokolliert.

import asyncio
from subscribeflow import SubscribeFlowClient

async def main():
    async with SubscribeFlowClient(api_key="sf_live_...") as client:
        # 1. Webhook für neue Subscriber erstellen
        webhook = await client.webhooks.create(
            url="https://your-app.com/webhooks/subscribeflow",
            events=[
                "subscriber.created",
                "subscriber.deleted",
                "tag.subscribed",
                "tag.unsubscribed",
            ],
            description="Alle Subscriber-Aktivitaeten verfolgen",
        )
        print(f"Webhook erstellt: {webhook.id}")
        print(f"Secret: {webhook.secret}")

        # 2. Endpoint testen
        result = await client.webhooks.test(webhook.id)
        if result.success:
            print("Endpoint verifiziert!")
        else:
            print(f"Test fehlgeschlagen: {result.error}")

asyncio.run(main())
import { SubscribeFlowClient } from '@subscribeflow/sdk';

const client = new SubscribeFlowClient({
  apiKey: 'sf_live_...',
});

// 1. Webhook für neue Subscriber erstellen
const webhook = await client.webhooks.create({
  url: 'https://your-app.com/webhooks/subscribeflow',
  events: [
    'subscriber.created',
    'subscriber.deleted',
    'tag.subscribed',
    'tag.unsubscribed',
  ],
  description: 'Alle Subscriber-Aktivitaeten verfolgen',
});

console.log('Webhook erstellt:', webhook.id);
console.log('Secret:', webhook.signing_secret);

// 2. Endpoint testen
const result = await client.webhooks.test(webhook.id, 'subscriber.created');
if (result.success) {
  console.log('Endpoint verifiziert!');
} else {
  console.log('Test fehlgeschlagen:', result.error);
}
# 1. Webhook erstellen (Secret aus der Antwort speichern!)
curl -X POST https://api.subscribeflow.net/api/v1/webhooks \
  -H "X-API-Key: sf_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/subscribeflow",
    "events": ["subscriber.created", "subscriber.deleted", "tag.subscribed", "tag.unsubscribed"],
    "description": "Alle Subscriber-Aktivitaeten verfolgen"
  }'

# 2. Endpoint testen
curl -X POST https://api.subscribeflow.net/api/v1/webhooks/WEBHOOK_ID/test \
  -H "X-API-Key: sf_live_..."