BetterFans Link API keys and scopes
Key types, the read and write scopes, account allow-lists, rotation and revocation.
Product page: OnlyFans agency API
Every request to BetterFans Link carries a key. The key decides the workspace, the mode, what the caller can do and which accounts it can see.
Key types
| Starts with | What it is |
|---|---|
bfl_live_ | A live secret key you create in the dashboard. It reads the accounts linked to your workspace. |
bfl_test_ | A test secret key you create in the dashboard. It reads the sandbox creators and never reaches OnlyFans or Fansly. |
bfl_oauth_ | A key an MCP client received through OAuth. You never handle it; revoke it by revoking the client. |
bfl_dash_ | The dashboard's own key. It never leaves BetterFans Link and is the only key that runs approved actions. |
You only ever create bfl_live_ and bfl_test_ keys. MCP clients that connect with OAuth get their own key, and the dashboard uses its own.
Sending a key
Send the key as a bearer token. The x-api-key header works too, for tools that cannot set Authorization.
curl https://betterfans.link/v1/me -H "Authorization: Bearer $BFL_KEY"
curl https://betterfans.link/v1/me -H "x-api-key: $BFL_KEY"Who am I returns the workspace, the key's mode, scopes and account list, and its rate limit. Call it first when something looks wrong.
How to get an OnlyFans or Fansly API key
OnlyFans and Fansly issue no API keys. You create a BetterFans Link key in the dashboard under Developers, then API keys: a bfl_test_ key for the sandbox creators, then a bfl_live_ key once a creator links an account.
Owners, admins and developers can create keys. Choose these settings.
| Setting | Options |
|---|---|
| Name | 1 to 60 characters. It appears in logs and on approvals, so name it after what uses it. |
| Access | Full access, Read and write with approval, or Read only. See Full access. |
| Accounts | Every account, or only the ones you pick. Full access always covers every account. |
| Expiry | Never, or after 1 to 365 days. |
The full key is shown once, when you create it. After that the dashboard shows only its first 12 and last 4 characters. Store it in a secret manager or an environment variable.
Full access
Full access gives a key read and write permission for every creator linked to its workspace, including creators added later. It skips approval for API actions and includes Direct access for live keys. Per-account write switches do not restrict Full access keys. Test keys still use only the sandbox.
An owner or admin can give an existing key Full access without changing its secret. On the key page, pick Full access under Access, choose Change access and type the key name. Revoking the key, removing a creator from the workspace, or an unavailable creator connection still prevents requests.
To take Full access away, pick Read and write with approval or Read only there instead. A key made before these choices existed shows as Custom access and keeps its settings until someone picks one.
Scopes
| Scope | Allows |
|---|---|
read | Every GET route, and creating hosted links with POST /v1/links. |
write | Creating actions with POST /v1/accounts/{accountId}/actions. Each action waits for a person to approve it, unless the key has auto-approve on. |
A key without the scope a route needs gets 403 missing_scope. Give a key write only if it asks for writes. A reporting job never needs it.
Account allow-lists
A key set to every account reaches every account linked to the workspace, including accounts linked after the key was made. A key limited to some accounts reaches only those.
For any other account, every route returns 404 account_not_found, exactly as if the account were not linked. List accounts returns the accounts the key can reach. In GET /v1/me, key.accountIds is null for a key set to every account.
Use an allow-list when a key serves one creator, or when you hand a key to someone who works on only some of your accounts.
Changing, rolling and revoking
- Change a key's name, access or accounts at any time on its page. The change takes effect within 30 seconds.
- Roll a key to replace its secret. The new key is shown once, and the old one keeps working for the time you choose: it stops now, in 1 hour or in 24 hours. Use the overlap to deploy the new key.
- Revoke a key to stop it for good. Revocation takes effect within 30 seconds.
A request with a revoked or expired key gets 401 revoked_api_key or expired_api_key.
Auto-approve
Auto-approve makes a key's writes run as soon as it asks for them. POST /v1/accounts/{accountId}/actions then answers 200 with the action already executed or failed, instead of 202 with a pending action. The action has autoApproved: true and still shows in Approvals and Logs. No action.pending webhook is sent; action.executed or action.failed is.
- Only a key with the
writescope can have it. MCP clients that sign in with OAuth and the dashboard key cannot. A test key can, and its writes stay simulated. - Full access turns it on. Read and write with approval and Read only turn it off. In live mode only owners and admins can change it; developers can in test mode. Every change shows in the audit log.
- For custom-access keys, the account's own writes switch applies. With writes off, the key gets
403writes_disabled. - Only an owner or admin can give an auto-approve key more accounts. Removing the
writescope turns auto-approve off. A rolled key keeps it only when an owner or admin rolls it. - Turning auto-approve off takes effect on the next write request.
Direct access
Direct access lets a live key also call the creator API. The creator API sends messages and makes other changes as your linked OnlyFans and Fansly accounts right away, with no approval. Actions you create with POST /v1/accounts/{accountId}/actions follow the key's auto-approve setting, not Direct access.
- Only a live key with the
writescope can have it. Test keys, the dashboard key and the keys of clients that sign in with OAuth cannot. - Full access turns it on for a live key, after an owner or admin types the key's name. Read and write with approval and Read only turn it off. Both show in the audit log.
- Custom-access keys also need the account's own writes switch, on its Settings page. With writes off, any request other than
GETorHEADgets403writes_disabled. Reads still work. - The key reaches the same accounts on the creator API as here. Only an owner or admin can give a key with Direct access more accounts.
- Removing the
writescope turns Direct access off. A rolled key keeps it only when an owner or admin rolls it. - Every request shows in Logs under the key's name.
Send the key as a bearer token or in the x-service-api-key header, never in a URL. The creator API has its own address, not the BetterFans Link API's. Ask us for it when you give a key Full access.
| Route | What it does |
|---|---|
GET /v1/accounts | Lists the OnlyFans accounts the key reaches. |
/v1/access/{accountId}/... | Calls OnlyFans as that account. |
GET /v1/fansly/accounts | Lists the Fansly accounts the key reaches. |
/v1/fansly/access/... | Calls Fansly as the account named in the x-fansly-account-id header. |
/v1/fansly/ws/connect?accountId=... | Opens a WebSocket of that Fansly account's live events. |
GET /v1/accounts and GET /v1/fansly/accounts answer 401 until the key has Direct access, which Full access gives a live key, so either one tells you whether it has taken effect. Each account they list carries writesEnabled, so you can tell which accounts take writes before you send. A test key, or a key with Direct access off, gets 401. A key without read gets 403 missing_scope on GET requests. An account the key cannot reach gets 403 account_not_found.
MCP clients
An MCP client that connects with OAuth, such as Claude.ai or ChatGPT, gets a workspace, a mode and scopes from the person who approves it on the consent page. It reaches every account in that workspace. The Developers, then MCP page lists connected clients. Disconnecting one there cuts it off, along with its tokens, within 30 seconds. See MCP.
Roles
People in a workspace have one of four roles. The role decides what they can do in the dashboard, including who can approve writes.
| Role | What they do |
|---|---|
| Owner | Everything an admin can do, plus deleting the workspace and adding or removing owners. |
| Admin | Manages the team and settings, removes accounts and approves writes. |
| Developer | Reads fan data and builds with keys, webhooks, connected apps and account links. Approves writes in test mode only. |
| Workspace viewer | Sees accounts, approvals, logs, usage, the team and the audit log. Cannot read fan data or change anything. |
Each role can do everything the role below it can. Test mode only touches sandbox creators, so a developer can also approve test writes there.
| Permission | Owner | Admin | Developer | Workspace viewer |
|---|---|---|---|---|
| See accounts, links, approvals, request logs, usage, keys, webhooks, the team and the audit log | Yes | Yes | Yes | Yes |
| Read fan data: fans, chats, messages, content, revenue detail and event payloads | Yes | Yes | Yes | No |
| Create keys and webhooks, connect apps and link accounts | Yes | Yes | Yes | No |
| Approve or reject writes and turn writes on or off for an account | Yes | Yes | Test mode only | No |
| Rename the workspace, invite and remove teammates, change roles, remove accounts and see invoices | Yes | Yes | No | No |
| Choose the plan, manage payment, delete the workspace and add or remove owners | Yes | No | No | No |
Keeping keys safe
- Use keys only on a server. Never put one in a browser, a mobile app or a public repository.
- Use a separate key for each service, so you can revoke one without breaking the others.
- If a key leaks, roll it with the old key set to stop now, then check its requests on the Logs page.
See security.