How Mass Messaging Works via API
Upload media, target fan segments, send at scale, and track revenue — all programmatically with real-time status callbacks.

Upload Media
Push photos or videos to OnlyFans CDN

Target Fans
Select user lists or individual fan IDs

Send Campaign
Mass message queued and sent progressively

Track Revenue
PPV unlock webhooks fire in real time
Real Webhook-Driven Mass Messaging Use Cases
Each use case shows the webhook event that triggers it and the API endpoint you call. Build these into your messaging pipeline.
Send PPV Campaigns to Fan Segments
Target specific user lists with PPV content. Upload media, set a price, and send to thousands of fans with a single API call.
Track PPV Unlock Revenue
Get notified the instant a fan unlocks a paid message. Track revenue per campaign and per fan in real time.
Build Smart Target Lists
Create user lists by segment — top spenders, recent subscribers, expired fans — and use them as mass message targets.
Upload and Attach Media
Upload photos and videos to the OnlyFans CDN, then attach them to mass messages as free or PPV content.
Monitor Campaign Performance
Track which messages drive the most revenue. See buyer lists, unlock rates, and top-performing content.
Schedule and Manage Queue
View queued messages, update pending campaigns, or cancel messages before they send. Full control over your send pipeline.
Production-Ready Code Examples
Real API calls for sending mass messages, tracking PPV revenue, and pulling campaign analytics.
// Step 1: Upload media to OnlyFans CDN
const mediaResponse = await fetch(
'https://app.fansapi.com/api/acct_XXXX/media/upload',
{
method: 'POST',
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
file_url: 'https://your-cdn.com/exclusive-content.mp4'
})
}
);
const media = await mediaResponse.json();
// Step 2: Send mass PPV message to a user list
const massMessageResponse = await fetch(
'https://app.fansapi.com/api/acct_XXXX/mass-messaging',
{
method: 'POST',
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: 'Exclusive content just for you 🔥',
price: 15.00,
mediaFiles: [media.data.id],
userLists: ['top_spenders_list_id']
})
}
);
const campaign = await massMessageResponse.json();
console.log('Campaign sent:', campaign.data.id);// Webhook handler: messages.ppv.unlocked
app.post('/webhooks/onlyfans', async (req, res) => {
const { event, account_id, payload } = req.body;
if (event === 'messages.ppv.unlocked') {
// payload.user = buyer profile
// payload.fanData.spending = lifetime spend breakdown
// payload.replacePairs['{AMOUNT}'] = purchase amount
const { user, fanData, replacePairs } = payload;
const purchaseAmount = replacePairs['{AMOUNT}'];
// Log the PPV unlock
console.log(
user.username + ' unlocked PPV for ' + purchaseAmount
);
// Update campaign revenue in your database
await db.campaigns.updateRevenue({
eventId: payload.id,
fanId: user.id,
fanUsername: user.username,
purchaseAmount: purchaseAmount,
fanLifetimeSpend: fanData.spending.total,
fanTipSpend: fanData.spending.tips,
fanMessageSpend: fanData.spending.messages,
});
// If whale spender, send a personalized follow-up
if (fanData.spending.total > 500) {
await fetch(
'https://app.fansapi.com/api/' + account_id + '/chats/' + user.id + '/messages',
{
method: 'POST',
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: 'Thanks for the support! Here is a bonus 💎'
})
}
);
}
}
res.sendStatus(200);
});// Get mass messaging overview
const overviewResponse = await fetch(
'https://app.fansapi.com/api/acct_XXXX/mass-messaging/overview',
{
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
}
}
);
const overview = await overviewResponse.json();
console.log('Total campaigns:', overview.data);
// Get engagement stats for mass messages
const engagementResponse = await fetch(
'https://app.fansapi.com/api/acct_XXXX/engagement/messages/mass-messages',
{
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
}
}
);
const engagement = await engagementResponse.json();
// Get the top revenue-generating message
const topMessageResponse = await fetch(
'https://app.fansapi.com/api/acct_XXXX/engagement/messages/top-message',
{
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
}
}
);
const topMessage = await topMessageResponse.json();
console.log('Top message:', topMessage.data);
// Get buyer list for a specific message
const buyersResponse = await fetch(
'https://app.fansapi.com/api/acct_XXXX/engagement/messages/'
+ topMessage.data.id + '/buyers',
{
headers: {
'Authorization': 'Bearer sk_your_api_key',
'Content-Type': 'application/json'
}
}
);
const buyers = await buyersResponse.json();
console.log('Buyers:', buyers.data);Available Endpoints and Webhooks
Every endpoint and webhook event for mass messaging. Full documentation at docs.fansapi.com.
Endpoints
- POST/api/{account}/mass-messaging
Send a mass message to user lists or user IDs.
- GET/api/{account}/mass-messaging
List all queued mass messages.
- GET/api/{account}/mass-messaging/overview
Get mass messaging overview statistics.
- GET/api/{account}/mass-messaging/{id}
Retrieve a specific mass message.
- PUT/api/{account}/mass-messaging/{id}
Update a pending mass message.
- DELETE/api/{account}/mass-messaging/{id}
Delete or unsend a mass message.
- POST/api/{account}/media/upload
Upload media to the OnlyFans CDN.
- GET/api/{account}/user-lists
List all user lists available for targeting.
- POST/api/{account}/user-lists
Create a new user list.
- POST/api/{account}/user-lists/{id}/users
Add users to an existing list.
- GET/api/{account}/engagement/messages/mass-messages
Retrieve mass message engagement statistics.
- GET/api/{account}/engagement/messages/top-message
Get the highest-revenue mass message.
- GET/api/{account}/engagement/messages/{id}/buyers
List buyers for a specific mass message.
Webhook Events
- EVENTchat_queue.finished
Mass message batch has completed sending to all recipients.
- EVENTchat_queue.updated
Mass message batch status changed — track sending progress.
- EVENTmessages.ppv.unlocked
Fan purchased a paid message, including purchase amount and spending data.
- EVENTmessages.sent
Outgoing message delivered to a fan — confirm delivery status.
- EVENTtransactions.new
Payment received — track PPV revenue alongside subscriptions and tips.

