{"pages":[{"slug":"index","title":"BetterFans Link","description":"OnlyFans API documentation for agencies and developers: REST routes, webhooks and an MCP server for OnlyFans and Fansly, with a test mode to build in.","url":"https://betterfans.link/docs","headings":["Is there an official OnlyFans or Fansly API?","Two ways in","How it works","Rules worth knowing first","For agents"]},{"slug":"fansly","title":"Fansly accounts","description":"Fansly API documentation for BetterFans Link: which routes and writes work on a linked Fansly account, API keys, linking, test mode and errors.","url":"https://betterfans.link/docs/fansly","headings":["What works on a Fansly account","API keys for Fansly","Link a Fansly account","Writes on a Fansly account","What is OnlyFans only","How fresh Fansly data is","Test mode with Sloane","Reads the routes do not cover","Fansly errors"]},{"slug":"get-started/quickstart-api","title":"API quickstart","description":"Create a test key, make your first call, read the response envelope and page through a list.","url":"https://betterfans.link/docs/get-started/quickstart-api","headings":["Create a test key","Make your first call","List the sandbox creators","Read the envelope","Page through a list","Handle errors","Next steps"]},{"slug":"get-started/quickstart-mcp","title":"MCP quickstart","description":"Connect an AI client to the BetterFans Link MCP server with OAuth or an API key, then ask it about your accounts.","url":"https://betterfans.link/docs/get-started/quickstart-mcp","headings":["The server URL","Choose how to sign in","Connect Claude Code","Ask your first question","Ask for a write","Teach the agent the rules"]},{"slug":"get-started/test-mode","title":"Test mode","description":"Build and test against sandbox creators with a test key. Test reads and writes never reach OnlyFans or Fansly.","url":"https://betterfans.link/docs/get-started/test-mode","headings":["Turn it on","The sandbox creators","Writes in test mode","Webhooks in test mode","What test mode does not do"]},{"slug":"get-started/going-live","title":"Going live","description":"Link a real creator with a hosted link, understand grants, and switch your code to a live key.","url":"https://betterfans.link/docs/get-started/going-live","headings":["Link a creator","Grants","The first sync","Switch to a live key","Turn on writes","Checklist"]},{"slug":"concepts/entities","title":"Entities and ids","description":"How workspaces, accounts, fans, chats and money fit together, and which id to pass where.","url":"https://betterfans.link/docs/concepts/entities","headings":["The model","Platforms","Platform ids","BetterFans Link ids","Fan-written text"]},{"slug":"concepts/money","title":"Money","description":"Every amount is an object with integer cents. Gross and net are different numbers; never add them together.","url":"https://betterfans.link/docs/concepts/money","headings":["The Money object","Gross, net and fee","Where the numbers come from","Totals you must not add","Paid messages"]},{"slug":"concepts/freshness","title":"Synced and live reads","description":"Reads come from synced data by default. Use fresh=true on the three routes that support it when the answer must be current.","url":"https://betterfans.link/docs/concepts/freshness","headings":["How old is the data","Reading live with fresh=true","Chats stay unread","Presence","Calling the platform directly","A newly linked account"]},{"slug":"concepts/account-status","title":"Account status","description":"The seven account statuses, which ones stop live calls, and what to do about each.","url":"https://betterfans.link/docs/concepts/account-status","headings":["The statuses","Fansly accounts","When live calls stop","Fixing a status","Watching for changes"]},{"slug":"concepts/writes-and-approvals","title":"Writes and approvals","description":"Writes wait for a person to approve them unless the key has auto-approve on. How actions work, from request to result.","url":"https://betterfans.link/docs/concepts/writes-and-approvals","headings":["The loop","What you need","Action types","Fansly accounts","Action statuses","Retrying safely","What the approver sees","Following the outcome","Test mode","Drafts are not writes"]},{"slug":"concepts/keys-and-scopes","title":"Keys and scopes","description":"Key types, the read and write scopes, account allow-lists, rotation and revocation.","url":"https://betterfans.link/docs/concepts/keys-and-scopes","headings":["Key types","Sending a key","How to get an OnlyFans or Fansly API key","Full access","Scopes","Account allow-lists","Changing, rolling and revoking","Auto-approve","Direct access","MCP clients","Roles","Keeping keys safe"]},{"slug":"concepts/rate-limits","title":"Rate limits","description":"Limits are per key. Read the RateLimit headers, and on 429 wait for Retry-After.","url":"https://betterfans.link/docs/concepts/rate-limits","headings":["The limits","Headers","When you hit the limit","Staying under it"]},{"slug":"concepts/plans-and-limits","title":"Plans and limits","description":"What a BetterFans Link plan limits, what counts as a live call, and what happens when a workspace reaches a limit.","url":"https://betterfans.link/docs/concepts/plans-and-limits","headings":["The limits","Live calls","When a workspace reaches a limit","Overage","Changing plan","Billing errors"]},{"slug":"concepts/requests-and-logs","title":"Requests and logs","description":"Request ids, the headers worth sending, and the request log in the dashboard.","url":"https://betterfans.link/docs/concepts/requests-and-logs","headings":["Request ids","Naming your app","The request log","The audit log"]},{"slug":"webhooks","title":"Set up webhooks","description":"Get a signed HTTPS request when a fan messages, a sale lands, an account changes status or an action is decided.","url":"https://betterfans.link/docs/webhooks","headings":["Add an endpoint","Event types","Which webhook events each platform sends","Receive an event","Send a test event","The signing secret","Deliveries","Events without an endpoint"]},{"slug":"concepts/security","title":"Security","description":"What BetterFans Link protects for you, what you are responsible for, and how to handle fan-written text safely.","url":"https://betterfans.link/docs/concepts/security","headings":["What BetterFans Link does","What you are responsible for","Fan-written text","Vault file URLs","MCP and OAuth","If a key leaks","Reporting a problem"]},{"slug":"api","title":"API overview","description":"OnlyFans and Fansly API reference for BetterFans Link: the base URL, API key authentication, the response envelope, pagination and every route.","url":"https://betterfans.link/docs/api","headings":["Base URL","Authentication","Responses","Meta","Lists","Pagination","Conventions","Errors","Routes","[Workspace](https://betterfans.link/docs/api/workspace)","[Accounts](https://betterfans.link/docs/api/accounts)","[Fans](https://betterfans.link/docs/api/fans)","[Chats](https://betterfans.link/docs/api/chats)","[Money](https://betterfans.link/docs/api/money)","[Content](https://betterfans.link/docs/api/content)","[Call OnlyFans](https://betterfans.link/docs/api/onlyfans)","[Call Fansly](https://betterfans.link/docs/api/fansly)","[Actions](https://betterfans.link/docs/api/actions)"]},{"slug":"api/workspace","title":"Workspace","description":"Check what a BetterFans Link API key can reach. One call to GET /v1/me returns its workspace, mode, scopes, accounts and rate limit.","url":"https://betterfans.link/docs/api/workspace","headings":["Who am I","Returns","Example request","Example response","The Me object"]},{"slug":"api/accounts","title":"Accounts","description":"OnlyFans and Fansly accounts API: list the creator accounts your key can use, check each one's status, and link new creators with a hosted link.","url":"https://betterfans.link/docs/api/accounts","headings":["List accounts","Query parameters","Returns","Example request","Example response","Errors","Create link","Request body","Returns","Example request","Example response","Errors","Get link","Path parameters","Returns","Example request","Example response","Errors","Get account","Path parameters","Returns","Example request","Example response","Errors","The Account object","The AccountDetail object","The HostedLink object"]},{"slug":"api/fans","title":"Fans","description":"OnlyFans fans API: find and rank fans by lifetime spend, read one fan's spend and subscription, list fan lists and see who is online now.","url":"https://betterfans.link/docs/api/fans","headings":["List fans","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Get fan","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Fan lists","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Online fans","Path parameters","Query parameters","Returns","Example request","Example response","Errors","The Fan object","The FanDetail object","The FanSummary object","The FanList object","The OnlineFans object"]},{"slug":"api/chats","title":"Chats","description":"OnlyFans chat API: list chats with unread counts and what each fan has spent, read the messages in a chat and search message text.","url":"https://betterfans.link/docs/api/chats","headings":["List chats","Path parameters","Query parameters","Returns","Example request","Example response","Errors","List messages","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Search messages","Path parameters","Query parameters","Returns","Example request","Example response","Errors","The Chat object","The Message object","The Media object"]},{"slug":"api/money","title":"Money","description":"OnlyFans transactions and earnings API: every sale with its fan, type, gross, net and fee, and revenue summaries by day, week or month.","url":"https://betterfans.link/docs/api/money","headings":["Revenue summary","Path parameters","Query parameters","Returns","Example request","Example response","Errors","List transactions","Path parameters","Query parameters","Returns","Example request","Example response","Errors","The RevenueSummary object","The Transaction object"]},{"slug":"api/content","title":"Content","description":"OnlyFans vault, posts and tracking links API: reach and sales of mass messages, top posts, subscribers and revenue per link, and vault media.","url":"https://betterfans.link/docs/api/content","headings":["Mass messages","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Top content","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Tracking links","Path parameters","Query parameters","Returns","Example request","Example response","Errors","Vault","Path parameters","Query parameters","Returns","Example request","Example response","Errors","The MassMessage object","The Post object","The TrackingLink object","The VaultItem object"]},{"slug":"api/onlyfans","title":"Call OnlyFans","description":"Read an OnlyFans API endpoint that no other route covers, for a linked OnlyFans account and with a live key. Reads only. Writes go through actions.","url":"https://betterfans.link/docs/api/onlyfans","headings":["Call OnlyFans","Path parameters","Returns","Example request","Example response","Errors"]},{"slug":"api/fansly","title":"Call Fansly","description":"Read a Fansly API endpoint from the reviewed list that no other route covers, for a linked Fansly account with a live key. Reads only.","url":"https://betterfans.link/docs/api/fansly","headings":["Call Fansly","Path parameters","Returns","Example request","Example response","Errors"]},{"slug":"api/actions","title":"Actions","description":"Send OnlyFans messages and mass messages through the API, take messages back and change fan lists, then follow each write to its result.","url":"https://betterfans.link/docs/api/actions","headings":["Create action","Path parameters","Request body","Returns","Example request","Example response","Errors","Send an OnlyFans message through the API","send_message","Send an OnlyFans mass message","send_mass_message","Other action types","unsend_message","add_fan_to_list","remove_fan_from_list","Get action","Path parameters","Returns","Example request","Example response","Errors","List actions","Query parameters","Returns","Example request","Example response","Errors","The Action object","Action statuses","Results"]},{"slug":"errors","title":"Errors","description":"OnlyFans API error codes from BetterFans Link: what each code and HTTP status means, which errors to retry and how to fix the rest.","url":"https://betterfans.link/docs/errors","headings":["The error body","Retrying","All codes","Invalid request","invalid_parameter","invalid_cursor","idempotency_key_required","method_not_allowed","not_supported_on_platform","Authentication","missing_api_key","invalid_api_key","revoked_api_key","expired_api_key","not_signed_in","invalid_access_token","Billing","quota_exceeded","plan_limit_reached","Permission","missing_scope","writes_disabled","missing_permission","dashboard_key_only","session_only","reauthentication_required","email_not_verified","workspace_suspended","staff_only","staff_protected","impersonation_read_only","Not found","account_not_found","fan_not_found","chat_not_found","action_not_found","link_not_found","route_not_found","workspace_not_found","resource_not_found","user_not_found","Conflict","idempotency_conflict","action_not_pending","action_expired","link_not_ready","last_owner","owns_workspaces","two_factor_enabled","two_factor_not_enabled","subscription_exists","no_subscription","subscription_active","checkout_unavailable","plan_not_available","last_admin","user_banned","email_unverified","account_in_use","Account unavailable","account_unavailable","Rate limited","rate_limited","Upstream","onlyfans_error","onlyfans_timeout","fansly_error","fansly_timeout","billing_provider_error","Internal","internal_error"]},{"slug":"webhooks/events","title":"Events","description":"OnlyFans webhook events and payloads: every event BetterFans Link sends for messages, sales, subscribers, accounts and actions, with its fields.","url":"https://betterfans.link/docs/webhooks/events","headings":["Headers","The event object","Event types","account.connected","account.status_changed","account.removed","link.failed","message.received","transaction.created","subscriber.new","action.pending","action.executed","action.rejected","action.failed","Test mode","Test events","When events start","Platforms"]},{"slug":"webhooks/verify","title":"Verify signatures","description":"Check that a webhook came from BetterFans Link before you act on it, with code for Node, Bun, Python and Go.","url":"https://betterfans.link/docs/webhooks/verify","headings":["How signing works","Node","Bun","Python","Go","Test vector","Rotate the secret","Sign a request yourself","When verification fails"]},{"slug":"webhooks/retries","title":"Retries and replay","description":"When BetterFans Link retries a webhook delivery, when it gives up and how to replay one.","url":"https://betterfans.link/docs/webhooks/retries","headings":["Schedule","Respond fast","Duplicates and order","Disabled endpoints","Replay"]},{"slug":"mcp","title":"MCP overview","description":"How the BetterFans Link MCP server works, how clients sign in to it, and what an agent gets from it.","url":"https://betterfans.link/docs/mcp","headings":["The server","Signing in","What an agent is told","Tool results","Platforms","The platform API tools","Fan-written text","Resources","Prompts","Test mode"]},{"slug":"mcp/clients","title":"Client setup","description":"Connect Claude Code, Claude, ChatGPT, Cursor, VS Code, Windsurf, Codex or Gemini CLI to the BetterFans Link MCP server.","url":"https://betterfans.link/docs/mcp/clients","headings":["Claude Code","Claude.ai and Claude Desktop","ChatGPT","Cursor","VS Code","Windsurf","Codex","Gemini CLI","Other clients","Check the connection"]},{"slug":"mcp/tools","title":"Tools and prompts","description":"Every BetterFans Link MCP tool for OnlyFans and Fansly: what it reads or asks to write, when an agent should call it, and the prompts.","url":"https://betterfans.link/docs/mcp/tools","headings":["Accounts","list_accounts","account_health","link_account","get_link","Fans","find_fans","get_fan","list_fan_lists","online_fans","Chats","list_chats","get_chat","search_messages","draft_message","Money","revenue_summary","list_transactions","Content","mass_message_performance","top_content","link_performance","list_vault","Platform API","search_api","describe_endpoint","call_api","Docs","search_docs","get_doc","Writes and approvals","send_message","send_mass_message","unsend_message","label_fan","get_action","Prompts"]},{"slug":"mcp/approvals","title":"Approvals for agents","description":"What an agent sees when it asks for a write over MCP, how a person approves it, and how the agent learns the outcome.","url":"https://betterfans.link/docs/mcp/approvals","headings":["The flow","What the agent gets back","Clients that open the link for you","Who can approve","Waiting for the outcome","Asking twice","When a write is refused","Test mode","Draft first"]},{"slug":"mcp/skills","title":"Agent skills","description":"Agent skills for the OnlyFans and Fansly API. Two skills teach an agent how BetterFans Link works and how to run agency jobs in Claude Code or Claude.ai.","url":"https://betterfans.link/docs/mcp/skills","headings":["The two skills","Claude Code","Claude.ai and Claude Desktop","Other agents","What the MCP server already says","Docs for agents"]},{"slug":"guides/link-a-creator","title":"Link a creator","description":"Send a creator a hosted link for OnlyFans or Fansly, follow their sign-in, handle a failure, and relink an account that needs it.","url":"https://betterfans.link/docs/guides/link-a-creator","headings":["Create the link","Send it to the creator","Follow progress","Link statuses","Steps the creator sees","When it connects","When it fails","Relink an account","Remove an account","In test mode"]},{"slug":"guides/daily-briefing","title":"Daily briefing","description":"A morning summary for every creator, with account problems, yesterday's revenue, top fans, chats worth answering and mass message results.","url":"https://betterfans.link/docs/guides/daily-briefing","headings":["With the API","With an agent","Reading the numbers","Next steps"]},{"slug":"guides/whales-and-churn","title":"Whales and churn","description":"Rank fans by lifetime spend, see what each one buys, and flag the big spenders who are slipping away before they are gone.","url":"https://betterfans.link/docs/guides/whales-and-churn","headings":["With the API","With an agent","What counts as at risk","Reading the numbers","Next steps"]},{"slug":"guides/reply-to-paying-fans","title":"Reply to unread paying fans","description":"Reply to paying OnlyFans and Fansly fans by API: find unread chats with fans who spent, draft replies in the creator's voice, and send each after review.","url":"https://betterfans.link/docs/guides/reply-to-paying-fans","headings":["Before you start","With the API","Find who is waiting","Ask for the send","Follow the outcome","With an agent","Writing replies that work"]},{"slug":"guides/moving-from-the-sdk","title":"Moving from the SDK","description":"How each part of the BetterFans Link SDK and the previous API maps to v1, what works differently, and what v1 does not have.","url":"https://betterfans.link/docs/guides/moving-from-the-sdk","headings":["What changed","Keys","How each part maps","A read, before and after","What is not in v1","Moving over"]}]}