OnlyFans API

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

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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 valuesDescription
messageA message has been sent to you
postPayment for a post
tipPayment for a tip
new_subscriptionPayment for a new subscription
recurring_subscriptionPayment for a recurring subscription
streamPayment for a stream
otherAnother type of transaction
Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
    "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).

Example payload
{
    "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.

Example payload
{
    "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.

Example payload
{
    "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.

Example payload
{
  "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.

Example data
{
  "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 expiredAt rather 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.
Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "event": "users.typing",
  "account_id": "acct_123",
  "payload": {
    "id": 1910197
  }
}

users.online

A fan was detected as online.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload
{
  "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.

Example payload (vault upload)
{
  "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:

Example payload (CDN upload)
{
  "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.

Example payload
{
  "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.

On this page