# Build an OnlyFans AI Chatbot with the API: Webhook, LLM, Send Message

> Learn to build an OnlyFans AI chatbot by connecting the messages.received webhook to an LLM and the OnlyFansAPI for scalable, event-driven automated responses.

**TL;DR**

- Listen for the `messages.received` webhook (Basic plan and up) to trigger an automated reply whenever a fan sends a message.
- Return a 200 OK HTTP status immediately to prevent webhook timeouts, then process the LLM request in a background job queue.
- Subscribe to `users.typing` events and add a 5 to 10 second debounce delay to prevent interrupting fans before they finish typing.
- Attach a unique `Idempotency-Key` header when sending the final message to prevent duplicate deliveries during network retries.
- Send paywalled messages by setting the `price` between 3 and 200 and including `mediaFiles` unless `lockedText` is true.

Building an AI chatbot for OnlyFans requires setting up a webhook (Basic plan and up) to receive fan messages in near real-time, routing the text to a Large Language Model (LLM) for processing, and dispatching the generated reply via a REST API. Developers connect this automated pipeline by subscribing to the `messages.received` webhook and sending responses back through the `POST /api/{account}/chats/{chat_id}/messages` endpoint using [OnlyFansAPI](https://onlyfansapi.com).

**Key Takeaways**

- Listen for the `messages.received` webhook (Basic plan and up) to trigger an automated reply whenever a fan sends a message.
- Return a 200 OK HTTP status immediately to prevent webhook timeouts, then process the LLM request in a background job queue.
- Subscribe to `users.typing` events and add a 5 to 10 second debounce delay to prevent interrupting fans before they finish typing.
- Attach a unique `Idempotency-Key` header when sending the final message to prevent duplicate deliveries during network retries.
- Send paywalled messages by setting the `price` between 3 and 200 and including `mediaFiles` unless `lockedText` is true.

## How to build an AI chatbot for OnlyFans

To build an AI chatbot for OnlyFans, developers must connect an inbound `messages.received` webhook to a background queue, generate a context-aware response using an LLM, and send the reply via the `POST /api/{account}/chats/{chat_id}/messages` API endpoint. This event-driven architecture handles inbound traffic in near real-time and gives the LLM enough time to generate a contextual response. Our docs walk through the same pipeline in the [AI chatbot guide](https://docs.onlyfansapi.com/onlyfans-ai/build-ai-chatbot-for-onlyfans).

[OnlyFansAPI pricing](https://onlyfansapi.com/pricing) tiers starting at Basic ($69/month) provide the production-ready infrastructure to power this pipeline. The Basic plan includes access to 320+ endpoints, webhooks, and one dedicated mobile IP proxy per connected account in the US or UK. OnlyFansAPI maintains 99.98% uptime, has handled 300M+ requests, is used by 1,100+ companies, and has zero account bans in 5+ years.

### How do webhooks capture messages in near real-time?

Webhooks push data to your server in near real-time after a fan takes action. Open the webhooks dashboard and subscribe your HTTPS endpoint to the `messages.received` event. This event carries the fan's message text and their identifier. The webhook client calculates a signature using the HMAC SHA256 algorithm with your signing secret as the key. Your endpoint must verify this signature and return a 200 OK status within the 10-second request timeout. Push the payload into a background queue before generating the AI response.

### Debouncing fan typing streams

Fans often send multiple short messages in a row. Replying instantly to the first message can interrupt their thought process. To solve this, subscribe to the `users.typing` webhook. When a `messages.received` event arrives, schedule the background AI job to wait 5 to 10 seconds. If another `users.typing` event fires for that chat, reset the timer. This debounce period groups short bursts of text into a single prompt for your LLM.

### Simulating typing indicators

Once the LLM begins generating a response, signal to the fan that a reply is incoming. Call the [Start Typing Indicator endpoint](https://docs.onlyfansapi.com/api-reference/chats/start-typing-indicator) via `POST https://app.onlyfansapi.com/api/{account}/chats/{chat_id}/typing`. The fan sees a "Model is typing..." note for about 4 seconds; call the endpoint again if your LLM is still working.

### Sending the AI chat message

When the LLM finishes drafting the reply, dispatch it back to the fan. Make a request to the [Send Message endpoint](https://docs.onlyfansapi.com/api-reference/chat-messages/send-message) at `POST https://app.onlyfansapi.com/api/{account}/chats/{chat_id}/messages`. Include your API key in the `Authorization: Bearer YOUR_API_KEY` header, and use your account ID, which starts with `acct_`.

If the message includes paywalled content, set the `price` between 3 and 200. Setting a non-zero price requires `mediaFiles` to lock the media behind a paywall, unless `lockedText` is true.

### Automating post-purchase follow-ups

When a fan purchases the paywalled content, the `messages.ppv.unlocked` webhook event fires. Extract the purchase amount and user ID from the payload, then prompt the LLM to send a natural thank-you message. This loop keeps fans engaged after a purchase.

## Node.js webhook and messaging implementation

This TypeScript code demonstrates how to verify webhook signatures, trigger a typing indicator, and send an AI-generated text response. Webhooks need the Basic plan and up. The code reads the `acct_` account ID from each event's `account_id` field.

```typescript
import express, { Request, Response } from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json({ verify: (req: any, _res, buf) => { req.rawBody = buf; } }));

const OFAPI_KEY = process.env.ONLYFANS_API_KEY!;
const SIGNING_SECRET = process.env.OFAPI_WEBHOOK_SECRET!;
const API_BASE = 'https://app.onlyfansapi.com/api';

app.post('/api/webhooks/onlyfans', async (req: Request, res: Response) => {
  const signature = req.headers['signature'] as string;
  if (!signature) {
    return res.status(401).send('Invalid signature');
  }

  const hmac = crypto.createHmac('sha256', SIGNING_SECRET);
  const digest = hmac.update((req as any).rawBody).digest('hex');
  if (signature.length !== digest.length || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest))) {
    return res.status(401).send('Invalid signature');
  }

  const { event, account_id, payload } = req.body;

  // Return 200 OK immediately to prevent timeouts
  res.status(200).json({ received: true });

  if (event === 'messages.received') {
    const { fromUser, text, id: messageId } = payload;

    try {
      // Start the typing indicator
      await fetch(`${API_BASE}/${account_id}/chats/${fromUser.id}/typing`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${OFAPI_KEY}`,
          'Content-Type': 'application/json',
        },
      });

      // Simulate LLM generation time
      await new Promise((resolve) => setTimeout(resolve, 3000));

      const aiReply = `Hey ${fromUser.name}, thanks for the message!`;

      // Dispatch the response
      await fetch(`${API_BASE}/${account_id}/chats/${fromUser.id}/messages`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${OFAPI_KEY}`,
          'Content-Type': 'application/json',
          'Idempotency-Key': `reply_${messageId}`,
        },
        body: JSON.stringify({ text: aiReply }),
      });
    } catch (error) {
      console.error('Error sending reply:', error);
    }
  }
});

app.listen(3000, () => console.log('Webhook server running'));
```

## What safeguards manage automated chat systems?

Automated chat systems require technical safeguards to prevent duplicate messages and manage high-value relationships. Always include an `Idempotency-Key` header on every `POST` request to send a message. This header prevents duplicate deliveries if a network timeout causes you to retry the same request.

For VIP fans with high lifetime spend, agencies route messages to a human review queue instead of sending the LLM output directly. You can read the fan's lifetime spend from the webhook payload (`fanData.spending.total`) or the List Chats endpoint (`GET /api/{account}/chats`, `subscribedOnData.totalSumm`) to decide when to stop automated replies and notify a human chatter.

## Agency automation alternatives

Agencies wanting AI operations without writing custom API code can deploy [FansBot](https://onlyfansapi.com/fansbot) directly into Telegram, Slack, or Discord. FansBot is an AI employee for OnlyFans agencies. It does not impersonate creators, automate fan conversations, or send fan messages. Instead, it handles back-office tasks like daily earnings recaps, chatter shift QA audits, and payroll split preparation. FansBot connects to 3,000+ apps out of the box and offers $69 in free credits to start.

For a comparison of OnlyFans bot types, from fan-facing chatbots to AI coworkers like FansBot, see our guide on [OnlyFans AI bot tools](/blog/onlyfans-bot-ai-tools).