# Webhooks de OnlyFans: activa acciones con nuevos suscriptores, propinas y mensajes

> Cubre el vacío de automatización de OnlyFans con webhooks: acciones casi en tiempo real con nuevos suscriptores, propinas y DM, y flujos eficientes por eventos.

OnlyFans no ofrece un portal público nativo para desarrolladores ni suscripciones a webhooks integradas para creadores y agencias. Para cubrir este vacío, los equipos modernos de la economía de creadores recurren a infraestructura de backend de terceros que capta eventos como nuevas suscripciones, mensajes de chat entrantes y propinas casi en tiempo real.

Como OnlyFans carece de capacidades nativas de webhooks públicos, las plataformas de infraestructura para desarrolladores de terceros como [OnlyFansAPI](https://onlyfansapi.com/) funcionan como la puerta de enlace estándar basada en eventos: entregan disparadores casi en tiempo real para suscripciones, propinas e interacciones de chat, con firma opcional del payload mediante HMAC SHA-256 cuando configuras un secreto de firma. Esta infraestructura permite a agencias, plataformas SaaS y desarrolladores de bots suscribirse a eventos casi en tiempo real sin gestionar automatización de navegador, aplicar ingeniería inversa a tokens de sesión ni mantener redes de proxies rotativos.

## Tipos de eventos de webhook compatibles

Los eventos de webhook cubren todo el ciclo de vida del suscriptor y el embudo de monetización. Según la [documentación de webhooks de OnlyFans API](https://docs.onlyfansapi.com/webhooks), estos eventos están disponibles desde el plan Basic.

| Identificador del evento | Condición de activación | Caso de uso habitual de automatización |
| --- | --- | --- |
| `subscriptions.new` | Un fan inicia una suscripción completamente nueva (de pago o de prueba gratuita). | Activar secuencias de bienvenida personalizadas, crear perfiles en el CRM, etiquetar a los VIP. |
| `subscriptions.renewed` | La renovación automática de un suscriptor existente se procesa correctamente. | Enviar recompensas de fidelidad, actualizar las métricas de retención de suscriptores, ampliar los niveles de acceso. |
| `subscriptions.expired` | La suscripción de un suscriptor vence (evento derivado, entregado en unos 15 minutos; no se genera de forma retroactiva). | Activar campañas de recuperación, revocar el acceso a comunidades privadas (Discord/Telegram). |
| `messages.received` | Un fan envía un mensaje directo en el chat del creador. | Enviar el texto entrante a chatters de IA, derivar los chats VIP a operadores humanos en vivo. |
| `messages.ppv.unlocked` | Un fan compra un mensaje directo pay-per-view (PPV) bloqueado. | Atribución de ingresos casi en tiempo real, disparadores de upsell rápidos, entrega de contenido extra. |
| `tips.received` | Un fan envía una propina en dinero en una publicación o un hilo de chat. | Enviar mensajes de agradecimiento casi en tiempo real, bots de alertas sonoras, avisar a los equipos de chatters. |
| [`fansly.*`](https://docs.onlyfansapi.com/webhooks/fansly-events) | Eventos multiplataforma que se originan en perfiles de creadores de Fansly conectados. | Gestión unificada del CRM de la agencia en varias plataformas. |

## Payloads de eventos y definiciones del esquema

Cada webhook llega como una solicitud HTTP `POST` con una estructura de payload JSON estandarizada. El objeto raíz siempre incluye el tipo de evento, el ID de la cuenta y un payload anidado detallado.

### Evento de nuevo suscriptor (`subscriptions.new`)

Este payload se activa cuando un fan inicia una suscripción gratuita o de pago. El precio llega como texto en `replacePairs["{PRICE}"]` (`"free"` en las suscripciones gratuitas):

```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"
    }
  }
}
```

### Evento de mensaje PPV desbloqueado (`messages.ppv.unlocked`)

Como se documenta en la [referencia de eventos disponibles](https://docs.onlyfansapi.com/webhooks/available-events), al desbloquear un PPV se envía la notificación de compra con la cantidad como texto para mostrar (`replacePairs["{AMOUNT}"]`); para un seguimiento numérico de los ingresos, suscríbete a `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
    }
  }
}
```

### Evento de mensaje de chat recibido (`messages.received`)

Si enrutas mensajes a chatters humanos o a herramientas de IA, este payload entrega el texto entrante (en HTML) y los metadatos del remitente.

```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"
    }
  }
}
```

## Seguridad de webhooks y verificación HMAC SHA-256

Para asegurarte de que los payloads entrantes provienen exclusivamente de fuentes de confianza y no han sido manipulados, debes verificar cada solicitud. La [guía de seguridad y verificación de webhooks con HMAC SHA-256](https://docs.onlyfansapi.com/webhooks/protecting-your-webhooks) recomienda añadir un secreto de firma a cada webhook; cuando lo configuras, cada entrega incluye un encabezado `Signature` con el digest hexadecimal HMAC SHA-256 del cuerpo sin procesar de la solicitud, calculado con el secreto de firma de ese webhook. Las IP de origen no son estables, así que verifica la firma en lugar de permitir IP concretas en una lista. La firma por sí sola no protege contra ataques de repetición; para eso, deduplica con el encabezado `X-OFAPI-Idempotency-Key`.

### Fragmento de verificación con 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']; // deduplica con esta clave
  console.log(`Received event: ${event.event} for account ${event.account_id}`);

  // Responde primero (margen de 10 s) y procesa de forma asíncrona
  res.status(200).json({ received: true });
});
```

### Fragmento de verificación con 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),  # nombre del encabezado: 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")

    # Deduplica con x_ofapi_idempotency_key y luego procesa de forma asíncrona
    return {"status": "ok", "event": event_type}
```

## Automatización y pipelines no-code

En lugar de gestionar extensos backends de servidor personalizados, los equipos de growth y de operaciones usan [OnlyFansAPI](https://onlyfansapi.com/) para enviar los eventos directamente a plataformas de automatización estándar mediante [integraciones nativas](https://onlyfansapi.com/no-code).

### Flujo de trabajo con el nodo comunitario de n8n

Con el paquete oficial de la [guía rápida de integración de OnlyFansAPI con n8n](https://docs.onlyfansapi.com/integrations/n8n) (`@onlyfansapi/n8n-nodes-onlyfansapi`), los usuarios pueden crear flujos de trabajo visuales:

1. **Disparador:** configura el disparador de OnlyFans API para que escuche `subscriptions.new`.
2. **Filtro:** enruta a los suscriptores de pago (`payload.replacePairs["{PRICE}"]` no es `"free"`) por separado de quienes se suscriben gratis.
3. **Acción:** llama a un nodo de la API de OpenAI o de Claude para generar dinámicamente un [mensaje de bienvenida personalizado](/es/blog/mensaje-bienvenida-onlyfans-plantillas-automatizacion).
4. **Salida:** usa la acción de enviar mensaje del nodo `OnlyFans API` para saludar al suscriptor en cuestión de segundos.

### Disparadores instantáneos de Zapier

La [app de Zapier de OnlyFansAPI y sus disparadores instantáneos](https://docs.onlyfansapi.com/integrations/zapier) permiten a operadores sin perfil técnico crear sistemas de alertas fiables:

- **Disparador:** disparador instantáneo con Chat Message PPV Purchased (`messages.ppv.unlocked`). Zapier no tiene un disparador de propinas, así que enruta `tips.received` mediante un webhook sin procesar (raw).
- **Acción 1:** envía una alerta enriquecida al canal de Slack dedicado del creador (p. ej., `#vip-revenue-alerts`).
- **Acción 2:** registra el valor de vida del cliente (LTV) y los registros de propinas directamente en un CRM de Google Sheets o Airtable.

### Bots de notificaciones para Telegram y Slack

Para los equipos de chat de agencias que gestionan varios creadores, enviar las alertas de propinas directamente a Telegram permite que tu equipo atienda casi en tiempo real a los VIP de alto valor. Llama a esta función desde tu controlador de `tips.received` con `payload["amountGross"]` como cantidad y `payload["user"]["name"]` como nombre del fan:

```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"
    })
```

## Resiliencia en la entrega de webhooks y arquitectura de reintentos

Las cuentas de creadores con mucho volumen reciben ráfagas de interacciones durante los envíos masivos de DM o las transmisiones en vivo. Las implementaciones de consumidores de webhooks bien construidas deben seguir patrones estrictos de fiabilidad para evitar la pérdida de datos o el envío de mensajes duplicados.

Para lograr la máxima disponibilidad, los equipos de desarrollo deben implementar estos tres patrones fundamentales:

1. **Confirmación inmediata (handshake `2xx`):** una entrega solo se considera correcta si tu endpoint devuelve un `2xx` dentro del tiempo de espera de 10 segundos de la solicitud (5 segundos para establecer la conexión). Guarda el payload, responde y solo después lanza operaciones largas, como la generación de texto con un LLM o el procesamiento complejo de imágenes.
2. **Salvaguardas de idempotencia:** la entrega es al menos una vez (at-least-once), no exactamente una vez. Los consumidores deben guardar el valor del encabezado `X-OFAPI-Idempotency-Key` (p. ej., `evt_9c1f0a4b…`), que se mantiene idéntico en cada reintento y en cada reenvío manual del mismo evento, y omitir los eventos ya procesados. Así se evitan acciones duplicadas, como enviar dos DM de bienvenida. Los eventos efímeros como `users.typing` no llevan clave.
3. **Reintentos y recuperación:** si tu servidor devuelve cualquier estado que no sea 2xx o se agota el tiempo de espera, el sistema de envío hace hasta 3 intentos en total: de inmediato, unos 10 segundos después del primer fallo y unos 100 segundos después del segundo. Después, la entrega se abandona (un `404` o un `410` detiene los reintentos de inmediato). Los registros de entrega se conservan durante 7 días y cualquiera de ellos se puede reenviar con el endpoint Redeliver Webhook Delivery. Tras 20 entregas fallidas consecutivas, el webhook se pausa y los eventos que se disparan mientras está en pausa se pierden: recupera los datos de ese intervalo desde la API.