# Auto-Send an OnlyFans Welcome Message When Someone Subscribes (subscriptions.new Webhook)

> Learn how to auto-send an OnlyFans welcome message using the subscriptions.new webhook. Use near real-time webhook events instead of manual polling.

**TL;DR**

- The `subscriptions.new` webhook (Basic plan and up) fires in near real-time when a new fan subscribes.
- Use the fan's ID from the payload's `user` (or `fan`) object, not the top-level `user_id` (that is the connected creator), as the `chat_id` for your API reply.
- Automated paid welcome messages require a price between 3 and 200 and a populated `mediaFiles` array, unless `lockedText` is true.
- Near real-time webhook events replace periodic polling of subscriber lists.
- Agencies can deploy welcome sequences via custom backend code or our own no-code packages for Zapier, Make, and n8n.

To auto-send an OnlyFans welcome message when someone subscribes, developers can listen for the `subscriptions.new` webhook event and trigger a POST request to the chat messages API. [OnlyFansAPI](https://fansapi.com) provides this webhook on the Basic plan and up, so free greetings or locked Pay-Per-View (PPV) media go out in near real-time after a fan subscribes.

**Key Takeaways**

- The `subscriptions.new` webhook (Basic plan and up) fires in near real-time when a new fan subscribes.
- Use the fan's ID from the payload's user (or fan) object, not the top-level `user_id` (that is the connected creator), as the `chat_id` for your API reply.
- Automated paid welcome messages require a price between 3 and 200 and a populated `mediaFiles` array, unless `lockedText` is true.
- Near real-time webhook events replace periodic polling of subscriber lists.
- Agencies can deploy welcome sequences via custom backend code or our own no-code packages for Zapier, Make, and n8n.

## Way to trigger webhooks on new subscribers

The way to trigger webhooks on new subscribers is to configure an endpoint to receive the `subscriptions.new` event, which dispatches an HTTP POST request containing the new subscriber's details in near real-time after they subscribe. Developers set up a server URL to receive this payload, verify the incoming event, and parse the fan's user ID to trigger follow-up actions like sending an automated welcome message.

This event-driven approach replaces manual polling of paginated subscriber lists. Listening for `subscriptions.new` requires a Basic plan ($69/mo) or higher, as the Free tier does not include webhook capabilities.

## Polling Methods vs. Near Real-Time Push

A major technical dividing line in creator operations is how systems identify new subscribers.

| Architectural Metric | Periodic Polling | Near Real-Time Push (`subscriptions.new`) |
| --- | --- | --- |
| **Detection Speed** | Set by your poll interval | Near real-time delivery |
| **Credit Efficiency** | 1 credit per uncached request, on every poll | 1 credit per 100 webhook events |
| **Deduplication** | Requires local database diff ledgers | `X-OFAPI-Idempotency-Key` header per event |
| **Infrastructure** | Heavy cron loops | Event-driven webhook handler |

Relying on webhooks gets the welcome message out in near real-time after the fan subscribes.

## Paid Message (PPV) Rules for Automations

When replying to a new subscriber, developers can send free text or attach locked Pay-Per-View (PPV) content. The API enforces specific rules on these direct messages.

- **Price Constraints:** Paid direct messages are priced from 3 to 200. The API accepts a price of 0 (free) or 3 to 200 and rejects any other value.
- **Mandatory Media Requirement:** All paid messages with a price greater than 0 must contain at least one media file, unless `lockedText` is true. A payload with a price, an empty `mediaFiles` array and no `lockedText` returns a 422 validation error.
- **Media ID Formats:** The `mediaFiles` parameter accepts temporary upload IDs generated via our API (e.g., `ofapi_media_123`) and permanent Vault Media IDs (e.g., `3866342509`). You can mix and match these IDs in the same array. Review our [media uploads guide](https://docs.fansapi.com/introduction/guides/uploading-media) for ID extraction workflows.
- **Free Previews:** To offer free teasers alongside locked media, pass the preview IDs in the `previews` array. Every media item listed in the `previews` array must also be present in the `mediaFiles` array.

## The subscriptions.new Webhook Payload

When a fan subscribes, the server dispatches a JSON payload containing the event details and subscriber profile. For a complete list of supported events and HMAC signature verification instructions, consult our [OnlyFans Webhooks Guide](https://fansapi.com/blog/onlyfans-webhooks-guide).

```json
{
  "event": "subscriptions.new",
  "account_id": "acct_123",
  "payload": {
    "id": "123",
    "type": "subscribed",
    "createdAt": "2026-10-04T12:00:00+00:00",
    "subType": "new_subscriber",
    "user_id": "222222222",
    "user": {
      "id": 987654321,
      "name": "Alex",
      "username": "alex99",
      "subscribePrice": 0,
      "isVerified": true,
      "canReceiveChatMessage": false
    }
  }
}
```

The `user_id` inside the payload is the connected creator's ID, not the subscriber's. The subscriber's ID sits in the user (and fan) object, and it is usually their chat ID for direct messaging.

## Implementation Code Examples

You can listen for the event and trigger a welcome message using the official SDKs or raw REST requests. Webhooks are delivered at least once, so both examples skip repeats of the same event using the `X-OFAPI-Idempotency-Key` header.

### TypeScript Node.js Implementation

```typescript
import express from 'express';
import OnlyFansAPI from '@onlyfansapi/onlyfans-sdk';

const app = express();
app.use(express.json());
const client = new OnlyFansAPI();
const seen = new Set<string>(); // use a persistent store in production

app.post('/webhooks/onlyfans', async (req, res) => {
  const { event, account_id, payload } = req.body;
  const eventKey = req.header('X-OFAPI-Idempotency-Key');

  // Answer first, then send
  res.sendStatus(200);
  if (eventKey) {
    if (seen.has(eventKey)) return;
    seen.add(eventKey);
  }

  if (event === 'subscriptions.new') {
    const fanId = String(payload.user.id);

    try {
      await client.chats.messages.send(fanId, {
        account: account_id,
        text: 'Hey! Thanks for subscribing 💜 Check your DMs for a surprise.',
      });

      await client.chats.messages.send(fanId, {
        account: account_id,
        text: 'Here is an exclusive welcome video just for you.',
        price: 9.99,
        mediaFiles: ['3866342509']
      });
    } catch (error) {
      console.error('Failed to send message');
    }
  }
});

app.listen(3000, () => console.log('Listening on port 3000'));
```

### Python Implementation

```python
import os
from fastapi import FastAPI, Request, Response
from onlyfansapi import OnlyFansAPI

app = FastAPI()
client = OnlyFansAPI()
seen = set()  # use a persistent store in production

@app.post("/webhooks/onlyfans")
async def handle_webhook(request: Request):
    event_key = request.headers.get("X-OFAPI-Idempotency-Key")
    if event_key in seen:
        return Response(status_code=200)
    if event_key:
        seen.add(event_key)

    data = await request.json()
    event = data.get("event")
    account_id = data.get("account_id")
    payload = data.get("payload", {})

    if event == "subscriptions.new":
        fan = payload.get("user", {})
        fan_id = str(fan.get("id"))

        client.chats.messages.send(
            fan_id,
            account=account_id,
            text="Hey! Thanks for subscribing 💕",
        )

        client.chats.messages.send(
            fan_id,
            account=account_id,
            text="Unwrap your exclusive welcome gift.",
            price=5.00,
            media_files=["3866342509"],
        )

    return Response(status_code=200)
```

### Raw REST Request

```bash
curl -X POST "https://app.fansapi.com/api/acct_123456789/chats/987654321/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Welcome to my VIP page! Here is a welcome treat.",
    "price": 10,
    "mediaFiles": ["3866342509"]
  }'
```

## No-Code Automation for Welcome Messages

Creators and agency operators can build these sequences without writing code using our [Zapier, Make, and n8n integrations](https://fansapi.com/no-code). These native packages connect directly to your account. Subscriber triggers run on webhooks, so they need the Basic plan and up.

- **Zapier Setup:** Select the OnlyFans API app and choose the New Subscriber trigger. Our Zapier app offers triggers only, so send the reply from n8n, Make or your own code.
- **Make Setup:** Add the OnlyFans API New Subscription trigger. Connect a Make a custom API call module that posts your text and optional price to the Send Message endpoint.
- **n8n Recommended:** Install our `@onlyfansapi/n8n-nodes-onlyfansapi` community node. Add an n8n webhook listener and point a `subscriptions.new` webhook at its URL. Use conditional logic to branch on the subscription price (`{PRICE}` in the payload), then add the OnlyFans API node to execute the Send Message operation.