BetterFans Link: the OnlyFans APIBetterFans Link

Approvals for agents

What an agent sees when it asks for a write over MCP, how a person approves it, and how the agent learns the outcome.

Product page: OnlyFans MCP server

An agent can read on its own. To change anything on OnlyFans or Fansly, it calls a write tool: send_message, send_mass_message, unsend_message or label_fan. Each one creates an action. For a client that signs in with OAuth, the action is pending until an owner or admin approves it in BetterFans Link. For a client that signs in with an API key, the action waits the same way unless the key has auto-approve on; then it runs at once and the tool returns the result. The rules are the same as for the REST API. See writes and approvals.

The flow

  1. The agent calls a write tool, for example send_message with the fan, the text and a price.
  2. BetterFans Link checks the request and creates a pending action.
  3. The tool returns the action with an approval link.
  4. The agent shares the link. A person opens it, reads what will happen and approves or rejects it.
  5. On approval the write runs on the account's platform. The agent checks the result with get_action.
ToolAction it creates
send_messagesend_message
send_mass_messagesend_mass_message
unsend_messageunsend_message
label_fanadd_fan_to_list or remove_fan_from_list

On a Fansly account only send_message and unsend_message work. A Fansly message goes to a fan who already has a chat with the creator, is free and attaches only free vault media. send_mass_message and label_fan return a not_supported_on_platform tool error there. See Fansly accounts.

What the agent gets back

The text result has:

  • The action's summary, in the words the approver will see.
  • The action id, which starts with act_, and its status.
  • The approval link, and when the action expires. A pending action expires after 24 hours.
  • For a mass message, the estimated number of fans it will reach.
  • In test mode, a line that says nothing is sent to OnlyFans or Fansly.

structuredContent holds the full Action. The approval link is approvalUrl.

While the action is pending, the agent should share the link and say plainly that nothing has been sent yet. It must not tell anyone a message was sent until get_action returns executed.

Clients that open the link for you

Clients on MCP protocol 2026-07-28 that support URL elicitation get more than a link. The tool asks the client to open the approval page. The client shows the action's summary and asks whether to open the page where you approve or reject it.

If you accept, the client opens the approval page in your browser. Opening it does not approve anything: you still approve or reject on the page. The tool then returns the action with its current status. If you decline, the action stays pending until it expires, and anyone who can approve can still find it on the Approvals page.

Older clients show the link in the tool result instead.

Who can approve

Owners and admins of the workspace can approve. Developers and workspace viewers can see pending actions but cannot decide them. The approver signs in to BetterFans Link, so an agent can never approve its own request.

The approval page shows the account, the fan or lists, the full text, the price, any media, and who asked. For an MCP request, that is the client name and the tool. The approver can approve or reject. They cannot edit the text, so the agent should draft it exactly as it should be sent.

Approvers also see every pending action on the Approvals page, and the action.pending webhook can alert them.

Waiting for the outcome

Call get_action with the action id.

StatusLabelMeaning
pendingWaiting for approvalWaiting for a person to approve or reject it. It expires after 24 hours.
approvedApprovedA person approved it and it is about to run.
rejectedRejectedA person rejected it. Nothing was sent.
expiredExpiredNobody decided within 24 hours. Nothing was sent.
executingRunningRunning on the account's platform.
executedDoneDone. result holds what the write returned.
failedFailedIt ran and did not succeed. error says why.

A person may take minutes or hours to decide. Do not call get_action in a tight loop. Tell the user the link, then check again when they say they decided, or every minute or so if the agent has to wait. Stop when the status is executed, rejected, expired or failed.

Asking twice

When the same client calls the same write tool with the same arguments again within the same 10 minute window, it gets the first pending action back instead of a second one. An agent that retries after a timeout does not queue duplicates. A change to any argument creates a new action.

When a write is refused

A refused write returns a tool error with a code and a hint, and creates no action.

CodeWhyWhat to do
missing_scopeThe key has no write scope.Add the scope to the key.
writes_disabledAPI writes are off for the account. They start off.An owner or admin turns on API writes on the account's Settings page.
invalid_parameterAn argument is missing or not valid, such as a price on a Fansly message.Fix the argument that param names.
not_supported_on_platformThe tool does not work for the account's platform.Use a tool that lists the account's platform.

An OAuth client without the write scope gets a 403 with insufficient_scope before the tool runs. The client can ask you to approve write access.

Test mode

With a test key, or an OAuth grant made in test mode, the flow is the same. Approving runs nothing on OnlyFans or Fansly: the action ends as executed with result.simulated set to true. Use it to see how your agent words its requests before it works on live accounts.

Draft first

draft_message gathers what a reply needs: the chat so far, what the fan has spent and bought, and paid messages they have not bought yet. It sends nothing and needs no approval. A good agent drafts, shows you the text, and calls send_message only once you agree with it.

On this page