Available OnlyFans webhook events
A list of all available OnlyFans webhook events that you can subscribe to.
Looking for a specific event?
Please reach out to us, we can add it!
Looking for Fansly? See the available Fansly webhook events.
Accounts
accounts.connected
A new OnlyFans account was connected.
Please note that payload.client_reference_id can be null - it's only
included if you provided us with client_reference_id while Creating Client
Session
{
"event": "accounts.connected",
"account_id": "acct_123",
"payload": {
"client_reference_id": "my_crm_model_12345", // Optional - Value you provided while creating Client Session - otherwise null
"state": "authenticated",
"progress": "started",
"latestAuthAttempt": {
"started_at": "2025-05-13T20:26:56.000000Z",
"completed_at": null,
"success": false,
"error_message": null,
"needs_otp": false,
"needs_face_otp": false,
"otp_phone_ending": null
}
}
}accounts.reconnected
An OnlyFans account was reconnected.
{
"event": "accounts.reconnected",
"account_id": "acct_123",
"payload": {
"state": "authenticated",
"progress": "started",
"latestAuthAttempt": {
"started_at": "2025-05-13T20:26:56.000000Z",
"completed_at": null,
"success": false,
"error_message": null,
"needs_otp": false,
"needs_face_otp": false,
"otp_phone_ending": null
}
}
}accounts.disconnected
An OnlyFans account was disconnected, either from the dashboard or with the Disconnect Account endpoint.
Every request for that acct_ ID from this point on returns a 404 with account_not_found, so stop polling it when this arrives.
Reconnecting gives you a new acct_ ID
The disconnected acct_ ID is never reused. If the creator reconnects later,
they come back as a new account, so key your own records on onlyfans_id (the
OnlyFans user ID, stable across reconnects) rather than on the acct_ ID.
{
"event": "accounts.disconnected",
"account_id": "acct_123",
"payload": {
"account_id": "acct_123",
"onlyfans_id": "123456789",
"onlyfans_username": "janedoe",
"disconnected_at": "2025-05-13T20:26:56+00:00"
}
}Not the same as a broken session
This event only fires when the account is deliberately disconnected. A
connection that breaks on its own gives you
accounts.session_expired or
accounts.authentication_failed instead, and
the account stays connected and usable in both of those cases.
accounts.session_expired
OnlyFans account connection has expired, but we automatically re-connected it using our system - you don't need to do anything.
{
"event": "accounts.session_expired",
"account_id": "acct_123",
"payload": {
"state": "authenticated",
"progress": "started",
"latestAuthAttempt": {
"started_at": "2025-05-13T20:26:56.000000Z",
"completed_at": null,
"success": false,
"error_message": null,
"needs_otp": false,
"needs_face_otp": false,
"otp_phone_ending": null
}
}
}accounts.authentication_failed
OnlyFans account connection has expired, and we couldn't automatically re-connect it using our system. You need to reconnect with our /authenticate endpoint or manually in our dashboard.
{
"event": "accounts.authentication_failed",
"account_id": "acct_123",
"payload": {
"state": "authenticated",
"progress": "started",
"latestAuthAttempt": {
"started_at": "2025-05-13T20:26:56.000000Z",
"completed_at": null,
"success": false,
"error_message": null,
"needs_otp": false,
"needs_face_otp": false,
"otp_phone_ending": null
}
}
}accounts.otp_code_required
A two-factor authentication code is required to connect one of your OnlyFans accounts.
{
"event": "accounts.otp_code_required",
"account_id": "acct_123",
"payload": {
"state": "authenticated",
"progress": "started",
"latestAuthAttempt": {
"started_at": "2025-05-13T20:26:56.000000Z",
"completed_at": null,
"success": false,
"error_message": null,
"needs_otp": false,
"needs_face_otp": false,
"otp_phone_ending": null
}
}
}accounts.face_otp_required
Face verification is required to connect one of your OnlyFans accounts.
{
"event": "accounts.face_otp_required",
"account_id": "acct_123",
"payload": {
"state": "authenticated",
"progress": "started",
"face_otp_verification_url": "https://id.onlyfans.com/s?123",
"latestAuthAttempt": {
"started_at": "2025-05-13T20:26:56.000000Z",
"completed_at": null,
"success": false,
"error_message": null,
"needs_otp": false,
"needs_face_otp": false,
"otp_phone_ending": null
}
}
}Transactions
transactions.new
A new transaction has been received from a fan (eg. a subscription, a tip, a post, etc.).
Please note that this event may be delayed by up to 3 minutes.
Supported payload.type values | Description |
|---|---|
message | A message has been sent to you |
post | Payment for a post |
tip | Payment for a tip |
new_subscription | Payment for a new subscription |
recurring_subscription | Payment for a recurring subscription |
stream | Payment for a stream |
other | Another type of transaction |
{
"event": "transactions.new",
"account_id": "acct_123",
"payload": {
"id": "abc123",
"created_at": "2026-01-01 00:00:00",
"type": "message",
"tips_source": null,
"amount": 10,
"vat_amount": 0,
"tax_amount": 0,
"net_amount": 8,
"fee_amount": 2,
"currency": "USD",
"description": "Payment for message from \"<a href=\"https://onlyfans.com/johndoe\">John Doe</a>\"",
"status": "loading",
"fan": {
"id": "123",
"username": "johndoe",
"name": "John Doe",
"display_name": "",
"avatar": null
},
"fanData": {
"available": true,
"last_updated_at": "2026-01-01T00:00:00.000000Z",
"spending": {
"total": 6.6,
"messages": 10,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0
},
"previous_reply_at": null
}
}
}Messages
messages.received
New message received from a fan.
{
"event": "messages.received",
"account_id": "acct_123",
"payload": {
"responseType": "message",
"text": "<p>Text</p>",
"giphyId": null,
"lockedText": false,
"isFree": true,
"price": 0,
"isMediaReady": true,
"mediaCount": 0,
"media": [],
"previews": [],
"isTip": false,
"isReportedByMe": false,
"isCouplePeopleMedia": false,
"queueId": 123,
"isMarkdownDisabled": true,
"fanData": {
"available": true,
"last_updated_at": "2025-10-23 00:52:34",
"spending": {
"total": 50,
"messages": 30,
"subscribes": 10,
"posts": 0,
"tips": 20,
"streams": 0
}
},
"fromUser": {
"view": "s",
"avatar": "https://example.com",
"avatarThumbs": {
"c50": "https://example.com",
"c144": "https://example.com"
},
"header": null,
"headerSize": null,
"headerThumbs": null,
"id": 123,
"name": "Name",
"username": "username",
"canLookStory": true,
"canCommentStory": true,
"hasNotViewedStory": false,
"isVerified": false,
"canPayInternal": true,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": false,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": false,
"canAddSubscriber": false,
"subscribePrice": 0,
"displayName": "",
"notice": "",
"isRestricted": false,
"canRestrict": true,
"subscribedBy": true,
"subscribedByExpire": false,
"subscribedByExpireDate": "2034-12-22T00:38:29+00:00",
"subscribedByAutoprolong": true,
"subscribedIsExpiredNow": false,
"currentSubscribePrice": 0,
"subscribedOn": true,
"subscribedOnExpiredNow": false,
"subscribedOnDuration": "4 months",
"listsStates": [
{
"id": "fans",
"type": "fans",
"name": "Fans",
"hasUser": true,
"canAddUser": false,
"cannotAddUserReason": "ALREADY_EXISTS"
},
{
"id": "following",
"type": "following",
"name": "Following",
"hasUser": true,
"canAddUser": false,
"cannotAddUserReason": "ALREADY_EXISTS"
},
{
"id": "recent",
"type": "recent",
"name": "Recent (last 24 hours)",
"hasUser": false,
"canAddUser": false,
"cannotAddUserReason": "SYSTEM_LIST"
},
{
"id": "muted",
"type": "muted",
"name": "Muted",
"hasUser": false,
"canAddUser": true,
"cannotAddUserReason": null
},
{
"id": "tagged",
"type": "tagged",
"name": "Tagged",
"hasUser": false,
"canAddUser": false,
"cannotAddUserReason": "SYSTEM_LIST"
},
{
"id": "friends",
"type": "friends",
"name": "Friends",
"hasUser": false,
"canAddUser": false,
"cannotAddUserReason": "USER_NOT_PERFORMER"
}
],
"showMediaCount": true,
"lastSeen": "2025-05-16T00:26:49+00:00",
"canReport": true
},
"isFromQueue": false,
"id": 123,
"isOpened": false,
"isNew": true,
"createdAt": "2025-05-16T00:27:25+00:00",
"changedAt": "2025-05-16T00:27:25+00:00",
"cancelSeconds": 120,
"isLiked": false,
"canPurchase": false,
"canPurchaseReason": "free",
"canReport": true,
"canBePinned": true,
"isPinned": false,
"replyToMessage": {
"responseType": "message",
"text": "<p>Text</p>",
"giphyId": null,
"lockedText": false,
"isFree": true,
"price": 0,
"isMediaReady": true,
"mediaCount": 0,
"media": [],
"previews": [],
"isTip": false,
"isReportedByMe": false,
"isCouplePeopleMedia": false,
"queueId": 123,
"isMarkdownDisabled": true,
"releaseForms": [],
"fromUser": {
"view": "s",
"avatar": "https://example.com",
"avatarThumbs": {
"c50": "https://example.com",
"c144": "https://example.com"
},
"header": "https://example.com",
"headerSize": {
"width": 4800,
"height": 1440
},
"headerThumbs": {
"w480": "https://example.com",
"w760": "https://example.com"
},
"id": 123,
"name": "Name",
"username": "username",
"canLookStory": true,
"canCommentStory": true,
"hasNotViewedStory": false,
"isVerified": true,
"canPayInternal": true,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": true,
"tipsEnabled": true,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": true,
"canAddSubscriber": false,
"subscribePrice": 0,
"hasStripe": false,
"isStripeExist": false,
"subscriptionBundles": [],
"canSendChatToAll": true,
"creditsMin": 10,
"creditsMax": 200,
"isPaywallPassed": true,
"creditsMinAlternatives": 5,
"canCreateLists": true,
"showMediaCount": true,
"lastSeen": "2025-05-16T00:24:06+00:00",
"canReport": false,
"subscribedOn": null
},
"isFromQueue": true,
"canUnsendQueue": true,
"unsendSecondsQueue": 1000000,
"id": 123,
"isOpened": false,
"isNew": false,
"createdAt": "2025-05-15T22:53:57+00:00",
"changedAt": "2025-05-15T22:53:57+00:00",
"cancelSeconds": 80792,
"isLiked": false,
"canPurchase": false,
"canPurchaseReason": "free",
"canReport": false,
"canBePinned": true,
"isPinned": false
}
}
}messages.sent
A new message has been sent from one of your OnlyFans accounts to a fan.
{
"event": "messages.sent",
"account_id": "acct_123",
"payload": {
"responseType": "message",
"text": "<p>Text</p>",
"giphyId": null,
"lockedText": false,
"isFree": true,
"price": 0,
"isMediaReady": true,
"mediaCount": 1,
"media": [
{
"id": 123,
"type": "photo",
"convertedToVideo": false,
"canView": true,
"hasError": false,
"createdAt": "2025-04-05T06:19:31+00:00",
"isReady": true,
"files": {
"full": {
"url": "https://example.com",
"width": 3840,
"height": 5215,
"size": 0,
"sources": []
},
"thumb": {
"url": "https://example.com",
"width": 300,
"height": 300,
"size": 0
},
"preview": {
"url": "https://example.com",
"width": 960,
"height": 1304,
"size": 0
},
"squarePreview": {
"url": "https://example.com",
"width": 960,
"height": 960,
"size": 0
}
},
"duration": 0,
"releaseForms": [],
"hasCustomPreview": false,
"videoSources": {
"240": null,
"720": null
}
}
],
"previews": [],
"isTip": false,
"isReportedByMe": false,
"isCouplePeopleMedia": false,
"queueId": 123,
"isMarkdownDisabled": true,
"releaseForms": [],
"isFromQueue": false,
"id": 123,
"isOpened": false,
"isNew": true,
"createdAt": "2025-05-15T23:37:24+00:00",
"changedAt": "2025-05-15T23:37:24+00:00",
"cancelSeconds": 86400,
"isLiked": false,
"canPurchase": false,
"canPurchaseReason": "free",
"canReport": false,
"canBePinned": true,
"isPinned": false,
"toUser": {
"view": "s",
"avatar": null,
"avatarThumbs": null,
"header": null,
"headerSize": null,
"headerThumbs": null,
"id": 123,
"name": "Name",
"username": "username",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": false,
"canPayInternal": true,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": false,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": false,
"canAddSubscriber": true,
"subscribePrice": 0,
"displayName": "",
"notice": "",
"isRestricted": false,
"canRestrict": true,
"subscribedBy": false,
"subscribedByExpire": null,
"subscribedByExpireDate": null,
"subscribedByAutoprolong": null,
"subscribedIsExpiredNow": null,
"currentSubscribePrice": null,
"subscribedOn": true,
"subscribedOnExpiredNow": false,
"subscribedOnDuration": "",
"listsStates": [
{
"id": "fans",
"type": "fans",
"name": "Fans",
"hasUser": true,
"canAddUser": false,
"cannotAddUserReason": "ALREADY_EXISTS"
},
{
"id": "following",
"type": "following",
"name": "Following",
"hasUser": false,
"canAddUser": false,
"cannotAddUserReason": "SYSTEM_LIST"
},
{
"id": "recent",
"type": "recent",
"name": "Recent (last 24 hours)",
"hasUser": true,
"canAddUser": false,
"cannotAddUserReason": "ALREADY_EXISTS"
},
{
"id": "muted",
"type": "muted",
"name": "Muted",
"hasUser": false,
"canAddUser": true,
"cannotAddUserReason": null
},
{
"id": "tagged",
"type": "tagged",
"name": "Tagged",
"hasUser": false,
"canAddUser": false,
"cannotAddUserReason": "SYSTEM_LIST"
},
{
"id": "friends",
"type": "friends",
"name": "Friends",
"hasUser": false,
"canAddUser": false,
"cannotAddUserReason": "USER_NOT_PERFORMER"
}
],
"showMediaCount": true,
"lastSeen": "2025-05-15T23:37:03+00:00",
"canReport": false
}
}
}messages.ppv.unlocked
A PPV message that you sent has been purchased by a fan.
{
"event": "messages.ppv.unlocked",
"account_id": "acct_123",
"payload": {
"id": "123",
"type": "paided_message",
"createdAt": "2025-05-05T22:18:00+00:00",
"text": "has purchased your <a href='https://onlyfans.com/my/chats/chat/123?firstId=123'>message</a> for $5.00!",
"replacePairs": {
"{NAME}": "Name",
"{MESSAGE_LINK}": "<a href='https://onlyfans.com/my/chats/chat/123?firstId=123'>message</a>",
"{AMOUNT}": "$5.00"
},
"subType": "subscriber_pay_for_chat_message",
"user_id": "123",
"isRead": false,
"canGoToProfile": true,
"fanData": {
"available": true,
"last_updated_at": "2026-01-02 17:12:00",
"spending": {
"total": 6.6,
"messages": 4,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0
}
},
"user": {
"avatar": null,
"avatarThumbs": null,
"header": null,
"headerSize": null,
"headerThumbs": null,
"id": 123,
"name": "Name",
"username": "username",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": false,
"canPayInternal": false,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": false,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": false,
"canAddSubscriber": false,
"subscribePrice": 0,
"subscribedBy": false,
"subscribedOn": false,
"canReceiveChatMessage": false,
"hideChat": false,
"lastSeen": "2025-05-05T22:17:29+00:00",
"isPerformer": false,
"isRealPerformer": false,
"view": "mn",
"canReport": true,
"subscribedByData": null,
"subscribedOnData": null,
"isBlocked": false
}
}
}messages.deleted
A chat message was deleted.
{
"event": "messages.deleted",
"account_id": "acct_123",
"payload": {
"id": "123"
}
}Chat Queue
chat_queue.updated
A queued message batch has been updated (e.g. progress change).
{
"event": "chat_queue.updated",
"account_id": "acct_123",
"payload": {
"id": 123,
"date": "2025-01-01T00:00:00+00:00",
"canUnsend": true,
"hasError": false,
"isCanceled": false,
"isCouplePeopleMedia": false,
"isDone": false,
"isReady": true,
"pending": 6,
"total": 7,
"unsendSeconds": 1000000
}
}chat_queue.finished
A queued message batch has finished sending.
{
"event": "chat_queue.finished",
"account_id": "acct_123",
"payload": {
"id": 123,
"date": "2025-01-01T00:00:00+00:00",
"canUnsend": false,
"hasError": false,
"isCanceled": true,
"isCouplePeopleMedia": false,
"isDone": true,
"isReady": true,
"pending": 0,
"total": 7,
"unsendSeconds": 0
}
}Tips
tips.received
A new tip has been received from a fan.
{
"event": "tips.received",
"account_id": "acct_123",
"payload": {
"amountGross": 5,
"amountNet": 4,
"fanData": {
"available": true,
"last_updated_at": "2026-01-02 17:12:00",
"spending": {
"total": 6.6,
"messages": 0,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0
}
},
"id": "123123123123",
"type": "tip",
"createdAt": "2026-01-02T17:12:00+00:00",
"text": "paid you a tip of $5.00",
"replacePairs": {
"{SUBSCRIBER_LINK}": "<a href='https:\/\/onlyfans.com\/xxxxxxxx'>John Doe<\/a>",
"{AMOUNT}": "$5.00",
"{POST_BLOCK}": "",
"{POST_DATA}": ""
},
"subType": "new_tips",
"user_id": "9999999999",
"isRead": false,
"canGoToProfile": true,
"user": {
"avatar": "https:\/\/public.onlyfans.com\/files\/u\/uf\/ufs\/ufsXXXXXXXXXXXXX\/111111111\/avatar.jpg",
"avatarThumbs": {
"c50": "https:\/\/thumbs.onlyfans.com\/public\/files\/thumbs\/c50\/u\/uf\/ufs\/ufsXXXXXXXXXXXXX\/111111111\/avatar.jpg",
"c144": "https:\/\/thumbs.onlyfans.com\/public\/files\/thumbs\/c144\/u\/uf\/ufs\/ufsXXXXXXXXXXXXX\/111111111\/avatar.jpg"
},
"header": "https:\/\/public.onlyfans.com\/files\/g\/g2\/g2e\/g2eXXXXXXXXXXXXXXX\/111111111\/header_image.jpg",
"headerSize": {
"width": 3362,
"height": 1780
},
"headerThumbs": {
"w480": "https:\/\/thumbs.onlyfans.com\/public\/files\/thumbs\/w480\/g\/g2\/g2e\/g2eXXXXXXXXXXXXXXX\/111111111\/header_image.jpg",
"w760": "https:\/\/thumbs.onlyfans.com\/public\/files\/thumbs\/w760\/g\/g2\/g2e\/g2eXXXXXXXXXXXXXXX\/111111111\/header_image.jpg"
},
"id": 111111111,
"name": "John Doe",
"username": "johndoe",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": false,
"canPayInternal": false,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": false,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": false,
"canAddSubscriber": false,
"subscribePrice": 0,
"subscribedBy": false,
"subscribedOn": false,
"canReceiveChatMessage": false,
"hideChat": false,
"lastSeen": "2026-01-02T17:09:46+00:00",
"isPerformer": false,
"isRealPerformer": false,
"view": "mn",
"canReport": true,
"subscribedByData": null,
"subscribedOnData": null,
"isBlocked": false
}
}
}Subscriptions
subscriptions.new
A new fan has subscribed.
{
"event": "subscriptions.new",
"account_id": "acct_123",
"payload": {
"id": "123",
"type": "subscribed",
"createdAt": "2025-05-05T21:27:00+00:00",
"text": "subscribed to your profile!",
"replacePairs": {
"{SUBSCRIBER_LINK}": "<a href='https://onlyfans.com/username'>Name</a>",
"{PRICE}": "free"
},
"subType": "new_subscriber",
"user_id": "123",
"isRead": false,
"canGoToProfile": true,
"fanData": {
"available": true,
"last_updated_at": "2026-01-02 17:12:00",
"spending": {
"total": 6.6,
"messages": 0,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0
}
},
"user": {
"avatar": "https://example.com",
"avatarThumbs": {
"c50": "https://example.com",
"c144": "https://example.com"
},
"header": "https://example.com",
"headerSize": {
"width": 767,
"height": 1152
},
"headerThumbs": {
"w480": "https://example.com",
"w760": "https://example.com"
},
"id": 123,
"name": "Name",
"username": "username",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": true,
"canPayInternal": false,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": true,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": true,
"canAddSubscriber": false,
"subscribePrice": 0,
"subscribedBy": false,
"subscribedOn": false,
"canReceiveChatMessage": false,
"hideChat": false,
"lastSeen": "2025-05-05T21:26:04+00:00",
"isPerformer": true,
"isRealPerformer": true,
"view": "mn",
"canReport": true,
"subscribedByData": null,
"subscribedOnData": null,
"isBlocked": false
}
}
}subscriptions.renewed
A fan has renewed their subscription.
{
"event": "subscriptions.renewed",
"account_id": "acct_123",
"payload": {
"id": "123",
"type": "subscribed",
"createdAt": "2025-05-05T21:27:00+00:00",
"text": "Good news! <a href='https://onlyfans.com/u34547118'>u34547118</a> has Just restarted their monthly subscription to your OnlyFans profile!",
"replacePairs": {
"{SUBSCRIBER_LINK}": "<a href='https://onlyfans.com/u34547118'>u34547118</a>",
"{PRICE}": "$4.00"
},
"subType": "returning_subscriber",
"user_id": "34547118",
"isRead": false,
"canGoToProfile": true,
"fanData": {
"available": true,
"last_updated_at": "2026-01-02 17:12:00",
"spending": {
"total": 6.6,
"messages": 0,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0
}
},
"user": {
"avatar": "https://example.com",
"avatarThumbs": {
"c50": "https://example.com",
"c144": "https://example.com"
},
"header": "https://example.com",
"headerSize": {
"width": 767,
"height": 1152
},
"headerThumbs": {
"w480": "https://example.com",
"w760": "https://example.com"
},
"id": 34547118,
"name": "Name",
"username": "username",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": true,
"canPayInternal": false,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": true,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": true,
"canAddSubscriber": false,
"subscribePrice": 0,
"subscribedBy": false,
"subscribedOn": false,
"canReceiveChatMessage": false,
"hideChat": false,
"lastSeen": "2025-05-05T21:26:04+00:00",
"isPerformer": true,
"isRealPerformer": true,
"view": "mn",
"canReport": true,
"subscribedByData": null,
"subscribedOnData": null,
"isBlocked": false
}
}
}subscriptions.expired
A fan's subscription has expired.
Unlike subscriptions.new and subscriptions.renewed, this event is derived. OnlyFans
emits no expiry signal, so we poll your expired subscribers hourly and deliver each lapse we
have not already sent you. Expect delivery within about an hour of the subscription lapsing.
Three things worth planning for:
- Subscriptions that had already lapsed before you enabled this event are not backfilled — you only receive lapses that happen from the moment you subscribe onwards. If another webhook on your team already watched that creator, you may receive lapses from up to an hour or so before you subscribed.
- Use
expiredAtrather than the delivery time to decide when a subscription actually ended. It is the value OnlyFans reports, and it is fixed at the moment we detect the lapse, so it stays correct even if the fan resubscribes before the webhook reaches you. - A fan who renews instead of lapsing produces no event. If they later lapse for real, the event fires then.
{
"event": "subscriptions.expired",
"account_id": "acct_123",
"payload": {
"id": "34547118:2025-05-05T21:27:00+00:00",
"type": "subscription_expired",
"subType": "expired_subscriber",
"createdAt": "2025-05-05T21:34:12+00:00",
"expiredAt": "2025-05-05T21:27:00+00:00",
"user_id": "34547118",
"user": {
"avatar": "https://example.com",
"avatarThumbs": {
"c50": "https://example.com",
"c144": "https://example.com"
},
"header": "https://example.com",
"headerSize": {
"width": 767,
"height": 1152
},
"headerThumbs": {
"w480": "https://example.com",
"w760": "https://example.com"
},
"id": 34547118,
"name": "Name",
"username": "username",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": true,
"canPayInternal": false,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": true,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": true,
"canAddSubscriber": false,
"subscribePrice": 12.99,
"subscribedBy": false,
"subscribedOn": false,
"canReceiveChatMessage": false,
"hideChat": false,
"lastSeen": "2025-05-04T09:12:31+00:00",
"isPerformer": true,
"isRealPerformer": true,
"view": "f",
"canReport": true,
"subscribedByData": null,
"subscribedOnData": {
"price": 12.99,
"newPrice": 12.99,
"regularPrice": 12.99,
"subscribePrice": 12.99,
"discountPercent": 0,
"discountPeriod": 1,
"subscribeAt": "2025-04-05T21:27:00+00:00",
"expiredAt": "2025-05-05T21:27:00+00:00",
"renewedAt": null,
"discountFinishedAt": null,
"discountStartedAt": null,
"status": null,
"isMuted": false,
"unsubscribeReason": "Redacted",
"duration": "1 month",
"tipsSumm": 15,
"subscribesSumm": 12.99,
"messagesSumm": 40.5,
"postsSumm": 0,
"streamsSumm": 0,
"totalSumm": 68.49,
"subscribes": [],
"hasActivePaidSubscriptions": false
},
"isBlocked": false
},
"fanData": {
"available": true,
"last_updated_at": "2025-05-05T21:34:11.000000Z",
"spending": {
"total": 68.49,
"messages": 40.5,
"subscribes": 12.99,
"posts": 0,
"tips": 15,
"streams": 0
},
"previous_reply_at": "2025-04-29T14:02:55.000000Z"
}
}
}Posts
posts.liked
A fan has liked one of your posts.
{
"event": "posts.liked",
"account_id": "acct_123",
"payload": {
"id": "123",
"type": "favorited",
"createdAt": "2025-05-05T22:22:00+00:00",
"text": "liked your <a href='https://onlyfans.com/123/username'>post</a>",
"replacePairs": {
"{POST_LINK}": "<a href='https://onlyfans.com/123/username'>post</a>"
},
"subType": "new_favorite",
"user_id": "123",
"isRead": false,
"canGoToProfile": true,
"user": {
"avatar": null,
"avatarThumbs": null,
"header": null,
"headerSize": null,
"headerThumbs": null,
"id": 123,
"name": "Name",
"username": "username",
"canLookStory": false,
"canCommentStory": false,
"hasNotViewedStory": false,
"isVerified": false,
"canPayInternal": false,
"hasScheduledStream": false,
"hasStream": false,
"hasStories": false,
"tipsEnabled": false,
"tipsTextEnabled": true,
"tipsMin": 5,
"tipsMinInternal": 1,
"tipsMax": 200,
"canEarn": false,
"canAddSubscriber": false,
"subscribePrice": 0,
"subscribedBy": false,
"subscribedOn": false,
"canReceiveChatMessage": false,
"hideChat": false,
"lastSeen": null,
"isPerformer": false,
"isRealPerformer": false,
"view": "mn",
"canReport": true,
"subscribedByData": null,
"subscribedOnData": null,
"isBlocked": false
}
}
}Users
users.typing
A fan is typing a message.
{
"event": "users.typing",
"account_id": "acct_123",
"payload": {
"id": 1910197
}
}users.online
A fan was detected as online.
{
"event": "users.online",
"account_id": "acct_123",
"payload": {
"fan": {
"id": "123",
"username": "johndoe",
"name": "John Doe",
"display_name": "John Doe",
"spending": {
"messages": 10,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0,
"total": 16.6
}
},
"observed_at": "2026-01-02T17:12:00.000000Z",
"status_changed_at": "2026-01-02T17:12:00.000000Z",
"last_seen_online_at": "2026-01-02T17:12:00.000000Z"
}
}users.offline
A fan that was previously detected as online was detected as offline.
{
"event": "users.offline",
"account_id": "acct_123",
"payload": {
"fan": {
"id": "123",
"username": "johndoe",
"name": "John Doe",
"display_name": "John Doe",
"spending": {
"messages": 10,
"subscribes": 2.6,
"posts": 0,
"tips": 4,
"streams": 0,
"total": 16.6
}
},
"observed_at": "2026-01-02T17:42:00.000000Z",
"status_changed_at": "2026-01-02T17:42:00.000000Z",
"last_seen_online_at": "2026-01-02T17:12:00.000000Z"
}
}These events are detected by periodic online-status polling, so delivery is not instant. users.online is emitted when a tracked fan transitions from unknown/offline to online. users.offline is emitted when a fan that was previously detected online is no longer present in a successful online-status check.
Data Exports
Data export webhook events are team-level events and do not include an account_id at the top level. Instead, the account_ids array is included in the payload.
data_exports.calculating_credits
Credit calculation has started for a data export.
{
"event": "data_exports.calculating_credits",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "calculating_credits",
"file_type": "csv",
"credit_cost": null,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00"
}
}data_exports.calculating_credits_completed
Credit calculation has completed successfully for a data export.
{
"event": "data_exports.calculating_credits_completed",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "calculating_credits_completed",
"file_type": "csv",
"credit_cost": 150,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00"
}
}data_exports.calculating_credits_failed
Credit calculation has failed for a data export.
{
"event": "data_exports.calculating_credits_failed",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "calculating_credits_failed",
"file_type": "csv",
"credit_cost": null,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00"
}
}data_exports.in_progress
A data export is now in progress.
{
"event": "data_exports.in_progress",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "in_progress",
"file_type": "csv",
"credit_cost": 150,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00"
}
}data_exports.completed
A data export has completed successfully. The payload includes a temporary download URL that expires after 1 hour.
{
"event": "data_exports.completed",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "completed",
"file_type": "csv",
"credit_cost": 150,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00",
"download_url": "https://example-bucket.s3.amazonaws.com/data-exports/team-slug/data_export_abc123xyz789.csv?X-Amz-Signature=...",
"download_url_expires_at": "2025-05-13T21:26:56+00:00"
}
}data_exports.failed
A data export has failed. The failed_reason field is only included when the failure was due to insufficient credits.
{
"event": "data_exports.failed",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "failed",
"file_type": "csv",
"credit_cost": 150,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00",
"failed_reason": "Insufficient credits: 150 required"
}
}data_exports.cancelled
A data export was cancelled.
{
"event": "data_exports.cancelled",
"payload": {
"id": "data_export_abc123",
"type": "transactions",
"status": "cancelled",
"file_type": "csv",
"credit_cost": 150,
"start_date": "2025-01-01T00:00:00+00:00",
"end_date": "2025-01-31T23:59:59+00:00",
"account_ids": ["acct_123", "acct_456"],
"created_at": "2025-05-13T20:26:56+00:00"
}
}Fan Summary
fan_summary.completed
An AI Fan Profile Summary has finished generating. This event fires for both new summaries and regenerations, and is dispatched after the summary completes successfully.
{
"event": "fan_summary.completed",
"data": {
"fan": {
"onlyfans_id": 123456789,
"username": "example_fan"
},
"summary": {
"status": "completed",
"summary_data": {
"name": "Jane Doe",
"preferred_name": "Jane",
"family_pets": "Has a golden retriever named Max",
"travel_plans": "Planning a trip to Bali",
"kinks": "",
"hobbies": "Yoga, photography",
"content_preferences": "Behind the scenes content",
"themes": "",
"requests": "",
"interests": "Fitness, travel",
"other_notes": ""
},
"analyzed_message_count": 504,
"last_analyzed_at": "2026-03-19T12:00:00+00:00"
}
}
}Media Uploads
These events only fire for asynchronous uploads (async=true). A synchronous upload returns its result in the response body, so there is nothing left to notify you about.
media_uploads.completed
An async media upload finished successfully. Fires for both Upload Media to OnlyFans CDN and Upload Media to Vault.
The payload carries the same fields as Get Upload Status, so you can subscribe to this event instead of polling the polling_url you got back from the 202 response.
{
"event": "media_uploads.completed",
"account_id": "acct_123",
"payload": {
"id": "ofapi_media_abc123def456abc123def456abc123de",
"prefixed_id": "ofapi_media_abc123def456abc123def456abc123de",
"account_id": "acct_123",
"status": "completed",
"file_name": "photo.jpg",
"created_at": "2026-04-03T16:17:58+00:00",
"media_id": 1234567890,
"media": {
"id": 1234567890,
"type": "photo",
"convertedToVideo": false,
"canView": true,
"hasError": false,
"createdAt": "2026-04-03T16:18:05+00:00",
"isReady": false,
"files": {
"full": { "url": null, "width": 0, "height": 0, "size": 0, "sources": [] },
"thumb": null,
"preview": null,
"squarePreview": null
},
"duration": 0,
"releaseForms": [],
"hasCustomPreview": false
},
"credits_used": 3,
"completed_at": "2026-04-03T16:18:05+00:00"
}
}Vault uploads carry the OnlyFans media ID in media_id. CDN uploads do not have one yet — they are referenced by prefixed_id (or media.processId) until you attach them to a post or message — so media_id is null there:
{
"event": "media_uploads.completed",
"account_id": "acct_123",
"payload": {
"id": "ofapi_media_abc123def456abc123def456abc123de",
"prefixed_id": "ofapi_media_abc123def456abc123def456abc123de",
"account_id": "acct_123",
"status": "completed",
"file_name": "photo.jpg",
"created_at": "2026-04-03T16:17:58+00:00",
"media_id": null,
"media": {
"prefixed_id": "ofapi_media_abc123def456abc123def456abc123de",
"file_name": "photo.jpg",
"processId": "abc123def456abc123de",
"host": "convert3.onlyfans.com",
"sourceUrl": "https://of2transcoder.s3.amazonaws.com/upload/00000000-0000-0000-0000-000000000000/000000000000/photo.jpg",
"extra": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...",
"additional": { "user": "123456789" },
"thumbs": [
{
"id": 1,
"url": "https://cdn2.onlyfans.com/files/0/00/00000000000000000000000000000000/300x544_00000000000000000000000000000000.jpg"
}
]
},
"credits_used": 3,
"completed_at": "2026-04-03T16:18:05+00:00"
}
}The prefixed_id can only be used once. After you include it in a post or message it is no longer valid, and you must upload the file again to get a new one.
media_uploads.failed
An async media upload failed. The error field carries the reason, and no credits are charged for the upload itself.
{
"event": "media_uploads.failed",
"account_id": "acct_123",
"payload": {
"id": "ofapi_media_abc123def456abc123def456abc123de",
"prefixed_id": "ofapi_media_abc123def456abc123def456abc123de",
"account_id": "acct_123",
"status": "failed",
"file_name": "photo.jpg",
"created_at": "2026-04-03T16:17:58+00:00",
"error": "Failed to download file from the provided URL.",
"failed_at": "2026-04-03T16:18:05+00:00"
}
}Common error values include a failed download from your file_url, a file larger than your subscription's upload limit, not enough credits to cover the upload, and Async upload staging expired before processing completed. Please retry. for an upload that sat unprocessed for more than 24 hours.
Protecting your webhooks
It is recommended to validate incoming webhook requests to ensure that they originate from OnlyFans API, and not from a malicious actor. You can do this by verifying the `Signature` header in the request.
Fansly events
A list of all available Fansly webhook events that you can subscribe to.