# OnlyFans-Webhooks: Aktionen bei neuen Abonnenten, Trinkgeldern & Nachrichten

> Schließ die Automatisierungslücke bei OnlyFans: Webhooks lösen Aktionen nahezu in Echtzeit bei neuen Abos, Trinkgeldern und DMs aus, für Event-Workflows.

OnlyFans bietet Creatorn und Agenturen weder ein natives öffentliches Entwicklerportal noch integrierte Webhook-Abonnements. Um diese Lücke zu schließen, setzen moderne Teams der Creator Economy auf Backend-Infrastruktur von Drittanbietern, die Events wie neue Abonnements, eingehende Chatnachrichten und Trinkgelder nahezu in Echtzeit erfasst.

Da OnlyFans keine nativen öffentlichen Webhook-Funktionen hat, dienen Entwickler-Infrastrukturplattformen von Drittanbietern wie [OnlyFansAPI](https://onlyfansapi.com/) als übliches ereignisgesteuertes Gateway: Sie liefern Trigger für Abonnements, Trinkgelder und Chat-Interaktionen nahezu in Echtzeit, optional mit HMAC-SHA-256-Signatur der Payload, wenn du ein Signing Secret festlegst. Mit dieser Infrastruktur können Agenturen, SaaS-Plattformen und Bot-Entwickler Events nahezu in Echtzeit abonnieren, ohne Browser-Automatisierung zu verwalten, Session-Tokens per Reverse Engineering nachzubauen oder rotierende Proxy-Netzwerke zu betreiben.

## Unterstützte Webhook-Event-Typen

Webhook-Events decken den gesamten Lebenszyklus eines Abonnenten und den Monetarisierungstrichter ab. Laut der [Webhook-Dokumentation der OnlyFans API](https://docs.onlyfansapi.com/webhooks) sind diese Events ab dem Basic-Plan verfügbar.

| Event-Bezeichner | Auslösebedingung | Typischer Anwendungsfall für Automatisierung |
| --- | --- | --- |
| `subscriptions.new` | Ein Fan startet ein brandneues Abonnement (kostenpflichtig oder als Free Trial). | Personalisierte Willkommenssequenzen auslösen, CRM-Profile anlegen, VIP-Tags vergeben. |
| `subscriptions.renewed` | Die automatische Verlängerung eines bestehenden Abonnenten wird erfolgreich verarbeitet. | Treueprämien senden, Retention-Kennzahlen der Abonnenten aktualisieren, Zugangsstufen verlängern. |
| `subscriptions.expired` | Das Abonnement eines Abonnenten läuft aus (abgeleitetes Event, Zustellung innerhalb von etwa 15 Minuten; kein Backfill). | Win-Back-Kampagnen auslösen, Zugang zur privaten Community entziehen (Discord/Telegram). |
| `messages.received` | Ein Fan sendet eine Direktnachricht im Creator-Chat. | Eingehenden Text an KI-Chatter übergeben, VIP-Chats an menschliche Live-Operatoren weiterleiten. |
| `messages.ppv.unlocked` | Ein Fan kauft eine gesperrte Pay-per-View-Direktnachricht (PPV). | Einnahmen-Attribution nahezu in Echtzeit, schnelle Trigger für Zusatzverkäufe, Auslieferung von Bonus-Content. |
| `tips.received` | Ein Fan sendet ein Trinkgeld zu einem Post oder in einem Chatverlauf. | Dankesnachrichten nahezu in Echtzeit senden, Sound-Alert-Bots auslösen, Chatter-Teams benachrichtigen. |
| [`fansly.*`](https://docs.onlyfansapi.com/webhooks/fansly-events) | Plattformübergreifende Events, die von verbundenen Fansly-Creator-Profilen stammen. | Einheitliches plattformübergreifendes CRM-Management für Agenturen. |

## Event-Payloads & Schema-Definitionen

Jeder Webhook kommt als HTTP-`POST`-Anfrage mit einer standardisierten JSON-Payload-Struktur an. Das Root-Objekt enthält immer den Event-Typ, die Account-ID und eine detaillierte verschachtelte Payload.

### Event für neue Abonnenten (`subscriptions.new`)

Diese Payload wird ausgelöst, wenn ein Fan ein kostenloses oder kostenpflichtiges Abonnement startet. Der Preis kommt als Text in `replacePairs["{PRICE}"]` an (`"free"` bei kostenlosen Abonnements):

```json
{
  "event": "subscriptions.new",
  "account_id": "acct_123",
  "payload": {
    "id": "123",
    "type": "subscribed",
    "createdAt": "2026-09-07T12:00:00+00:00",
    "text": "subscribed to your profile!",
    "replacePairs": {
      "{SUBSCRIBER_LINK}": "<a href='https://onlyfans.com/alex_vip'>Alex</a>",
      "{PRICE}": "free"
    },
    "subType": "new_subscriber",
    "user_id": "8923411",
    "isRead": false,
    "canGoToProfile": true,
    "fanData": {
      "available": true,
      "last_updated_at": "2026-09-07 12:00:00",
      "spending": { "total": 0, "messages": 0, "subscribes": 0, "posts": 0, "tips": 0, "streams": 0 }
    },
    "user": {
      "id": 8923411,
      "name": "Alex",
      "username": "alex_vip",
      "avatar": "https://example.com",
      "isVerified": false,
      "subscribedBy": false,
      "tipsMin": 5,
      "lastSeen": "2026-09-07T11:58:32+00:00"
    }
  }
}
```

### Event für entsperrte PPV-Nachrichten (`messages.ppv.unlocked`)

Wie in der [Referenz der verfügbaren Events](https://docs.onlyfansapi.com/webhooks/available-events) dokumentiert, sendet das Entsperren einer PPV-Nachricht die Kaufbenachrichtigung mit dem Betrag als Anzeigetext (`replacePairs["{AMOUNT}"]`); für numerisches Umsatz-Tracking abonnierst du `transactions.new`:

```json
{
  "event": "messages.ppv.unlocked",
  "account_id": "acct_123",
  "payload": {
    "id": "992144",
    "type": "paided_message",
    "createdAt": "2026-09-07T14:22:00+00:00",
    "text": "has purchased your <a href='https://onlyfans.com/my/chats/chat/123?firstId=992144'>message</a> for $25.00!",
    "replacePairs": {
      "{NAME}": "FanName",
      "{AMOUNT}": "$25.00"
    },
    "subType": "subscriber_pay_for_chat_message",
    "user_id": "554123",
    "user": {
      "id": 554123,
      "name": "HighValueFan",
      "username": "hv_fan99",
      "tipsMin": 5,
      "subscribePrice": 0,
      "isBlocked": false
    }
  }
}
```

### Event für empfangene Chatnachrichten (`messages.received`)

Wenn du Nachrichten an menschliche Chatter oder KI-Tools weiterleitest, liefert diese Payload den eingehenden Text (als HTML) und die Metadaten des Absenders.

```json
{
  "event": "messages.received",
  "account_id": "acct_abc123",
  "payload": {
    "responseType": "message",
    "text": "<p>Hey! Loved your recent set. Are custom requests open?</p>",
    "giphyId": null,
    "lockedText": false,
    "isFree": true,
    "price": 0,
    "isMediaReady": true,
    "mediaCount": 0,
    "media": [],
    "isTip": false,
    "fromUser": {
      "id": 441029,
      "name": "JohnDoe",
      "username": "johndoe",
      "avatar": "https://public.onlyfans.com/files/avatar/user.jpg"
    }
  }
}
```

## Webhook-Sicherheit & HMAC-SHA-256-Verifizierung

Um sicherzustellen, dass eingehende Payloads ausschließlich aus vertrauenswürdigen Quellen stammen und nicht manipuliert wurden, solltest du jede Anfrage verifizieren. Der [Leitfaden zu HMAC-SHA-256-Webhook-Sicherheit & -Verifizierung](https://docs.onlyfansapi.com/webhooks/protecting-your-webhooks) empfiehlt, jedem Webhook ein Signing Secret hinzuzufügen. Ist eines gesetzt, trägt jede Zustellung einen `Signature`-Header mit dem HMAC-SHA-256-Hex-Digest des rohen Anfrage-Bodys, berechnet mit dem Signing Secret dieses Webhooks als Schlüssel. Die Quell-IPs sind nicht stabil, also verifiziere die Signatur, statt IPs auf eine Allowlist zu setzen. Die Signatur allein schützt nicht vor Replays; dedupliziere stattdessen anhand des `X-OFAPI-Idempotency-Key`-Headers.

### Verifizierungs-Snippet für Node.js / Express

```javascript
const crypto = require('crypto');
const express = require('express');
const app = express();

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

app.post('/webhook/onlyfans', (req, res) => {
  const signature = req.headers['signature'] || '';
  const signingSecret = process.env.ONLYFANS_WEBHOOK_SECRET;

  const computedSignature = crypto
    .createHmac('sha256', signingSecret)
    .update(req.body)
    .digest('hex');

  const a = Buffer.from(signature);
  const b = Buffer.from(computedSignature);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body.toString());
  const idempotencyKey = req.headers['x-ofapi-idempotency-key']; // anhand dieses Werts deduplizieren
  console.log(`Received event: ${event.event} for account ${event.account_id}`);

  // Zuerst antworten (10 s Zeitbudget), dann asynchron verarbeiten
  res.status(200).json({ received: true });
});
```

### Verifizierungs-Snippet für Python / FastAPI

```python
import hmac
import hashlib
import json
from fastapi import FastAPI, Request, HTTPException, Header

app = FastAPI()
SIGNING_SECRET = "your_webhook_signing_secret"

@app.post("/webhook/onlyfans")
async def handle_onlyfans_webhook(
    request: Request,
    signature: str = Header(None),  # Header-Name: Signature
    x_ofapi_idempotency_key: str = Header(None),
):
    body = await request.body()
    computed_signature = hmac.new(
        SIGNING_SECRET.encode(),
        body,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(computed_signature, signature or ""):
        raise HTTPException(status_code=401, detail="Invalid HMAC signature")

    payload = json.loads(body)
    event_type = payload.get("event")

    # Anhand von x_ofapi_idempotency_key deduplizieren, dann asynchron verarbeiten
    return {"status": "ok", "event": event_type}
```

## Automatisierung & No-Code-Pipelines

Statt umfangreiche eigene Server-Backends zu verwalten, nutzen Growth- und Operations-Teams [OnlyFansAPI](https://onlyfansapi.com/), um Events über [native Integrationen](https://onlyfansapi.com/no-code) direkt in gängige Automatisierungsplattformen zu leiten.

### Workflow mit dem n8n Community Node

Mit dem offiziellen Paket aus dem [Quickstart zur n8n-Integration von OnlyFansAPI](https://docs.onlyfansapi.com/integrations/n8n) (`@onlyfansapi/n8n-nodes-onlyfansapi`) kannst du visuelle Workflows bauen:

1. **Trigger:** Richte den OnlyFans-API-Trigger so ein, dass er auf `subscriptions.new` hört.
2. **Filter:** Leite zahlende Abonnenten (`payload.replacePairs["{PRICE}"]` ist nicht `"free"`) getrennt von denen weiter, die kostenlos einsteigen.
3. **Aktion:** Ruf einen OpenAI- oder Claude-API-Node auf, um dynamisch eine [individuelle Willkommensnachricht](/de/blog/onlyfans-willkommensnachricht-vorlagen-automatisierung) zu generieren.
4. **Ausgabe:** Nutze die Aktion „Send Message“ des `OnlyFans API`-Nodes, um den Abonnenten innerhalb von Sekunden zu begrüßen.

### Instant Triggers in Zapier

Mit der [OnlyFansAPI-Zapier-App & Instant Triggers](https://docs.onlyfansapi.com/integrations/zapier) bauen auch Operatoren ohne technischen Hintergrund zuverlässige Alert-Systeme:

- **Trigger:** Instant Trigger bei Chat Message PPV Purchased (`messages.ppv.unlocked`). Zapier hat keinen Trinkgeld-Trigger, leite `tips.received` daher stattdessen über einen direkten Webhook.
- **Aktion 1:** Sende einen formatierten Alert in den eigenen Slack-Channel eines Creators (z. B. `#vip-revenue-alerts`).
- **Aktion 2:** Trag den Customer Lifetime Value (LTV) und Trinkgeld-Einträge direkt in ein CRM in Google Sheets oder Airtable ein.

### Benachrichtigungs-Bots für Telegram & Slack

Für Chat-Teams von Agenturen, die mehrere Creator betreuen, sorgen Trinkgeld-Alerts direkt in Telegram dafür, dass sich das Team nahezu in Echtzeit um wertvolle VIPs kümmert. Ruf diese Funktion in deinem `tips.received`-Handler auf, mit `payload["amountGross"]` als Betrag und `payload["user"]["name"]` als Namen des Fans:

```python
import requests

def send_telegram_alert(bot_token, chat_id, fan_name, tip_amount, creator_handle):
    message = (
        f"🚨 *NEW TIP RECEIVED*\n"
        f"• *Creator:* @{creator_handle}\n"
        f"• *Fan:* {fan_name}\n"
        f"• *Amount:* ${tip_amount:.2f}\n"
        f"⚡ *Action Required:* Prioritize reply in chat."
    )
    url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
    requests.post(url, json={
        "chat_id": chat_id,
        "text": message,
        "parse_mode": "Markdown"
    })
```

## Resilienz der Webhook-Zustellung & Retry-Architektur

Creator-Accounts mit hohem Volumen erleben beim Versand von Massennachrichten oder bei Livestreams Interaktionsspitzen. Belastbare Implementierungen von Webhook-Consumern müssen strikte Zuverlässigkeitsmuster einhalten, um Datenverlust oder doppelt gesendete Nachrichten zu verhindern.

Um maximale Uptime sicherzustellen, sollten Entwicklungsteams diese drei grundlegenden Muster umsetzen:

1. **Sofortige Bestätigung (`2xx`-Handshake):** Eine Zustellung gilt nur dann als erfolgreich, wenn dein Endpunkt innerhalb des Anfrage-Timeouts von 10 Sekunden (5 Sekunden für den Verbindungsaufbau) einen `2xx`-Status zurückgibt. Speichere die Payload, antworte und starte erst danach langwierige Vorgänge wie LLM-Textgenerierung oder aufwendige Bildverarbeitung.
2. **Idempotenz-Absicherung:** Die Zustellung erfolgt mindestens einmal (at-least-once), nicht genau einmal (exactly-once). Consumer müssen den Wert des `X-OFAPI-Idempotency-Key`-Headers speichern (z. B. `evt_9c1f0a4b…`), der bei jedem erneuten Versuch und jeder manuellen erneuten Zustellung desselben Events identisch bleibt, und bereits verarbeitete Events überspringen. So verhinderst du doppelte Aktionen, etwa zwei Willkommensnachrichten per DM. Flüchtige Events wie `users.typing` haben keinen Schlüssel.
3. **Erneute Versuche & Wiederherstellung:** Gibt dein Server einen Status außerhalb von 2xx zurück oder läuft er in ein Timeout, unternimmt der Dispatcher insgesamt bis zu 3 Zustellversuche: sofort, etwa 10 Sekunden nach dem ersten Fehlschlag und etwa 100 Sekunden nach dem zweiten. Danach wird die Zustellung aufgegeben (ein `404` oder `410` beendet die erneuten Versuche sofort). Zustellungsdatensätze werden 7 Tage lang aufbewahrt, und jeder davon lässt sich über den Endpunkt Redeliver Webhook Delivery erneut senden. Nach 20 aufeinanderfolgenden fehlgeschlagenen Zustellungen wird der Webhook pausiert, und Events, die während der Pause ausgelöst werden, gehen verloren: Hol die Daten für diesen Zeitraum über die API nach.