BetterFans Link: the OnlyFans APIBetterFans Link

Set up webhooks

Get a signed HTTPS request when a fan messages, a sale lands, an account changes status or an action is decided.

Webhooks tell your server when something happens, so you do not have to poll. BetterFans Link sends a signed POST with a JSON body to each endpoint that subscribes to the event's type.

Add an endpoint

  1. In the dashboard, open Developers, then Webhooks, and add an endpoint.
  2. Enter its URL. It must start with https://.
  3. Pick the event types it should get. You can change them later.
  4. Copy the signing secret. It starts with whsec_.

Owners, admins and developers can add and change endpoints.

An endpoint belongs to the mode it was created in and gets only events of that mode. Create it with Test mode off for live accounts. Create it with Test mode on to test your handler: test mode sends the action.* events for actions made with a test key, and account.connected and link.failed for hosted links made with a test key. Account status, message, sale and subscriber events come only from linked accounts in live mode. See test mode events. Most teams keep one endpoint of each mode.

Event types

TypeWhen it is sent
account.connectedAn OnlyFans account was linked to the workspace.
account.status_changedAn account's status changed, for example to Needs relink.
account.removedAn account was removed from the workspace.
link.failedA hosted link session ended without connecting.
message.receivedA fan sent a message.
transaction.createdA fan paid for something: a subscription, tip, message, post or stream.
subscriber.newA fan subscribed or resubscribed.
action.pendingAn API client asked for a write that needs approval.
action.executedAn approved write ran on OnlyFans.
action.rejectedA person rejected a pending write.
action.failedAn approved write failed on OnlyFans.

Every event has the same envelope, with the type-specific fields in data. See events and payloads.

Receive an event

Your endpoint has to do four things.

  1. Read the raw body before any JSON parsing, and verify the signature against it.
  2. Drop events whose webhook-id you have already handled. The same event can arrive more than once.
  3. Store the event and answer with any 2xx status within 15 seconds.
  4. Do the slow work afterwards, from your own queue.
// Bun. See the verify page for Node, Python and Go.
import { verifyWebhook } from "./verify";

Bun.serve({
  port: 3000,
  async fetch(req) {
    const body = await req.text();
    if (!verifyWebhook(process.env.BFL_WEBHOOK_SECRET!, req.headers, body)) {
      return new Response("bad signature", { status: 400 });
    }
    const event = JSON.parse(body);
    if (await alreadyHandled(event.id)) return new Response("ok");
    await enqueue(event);
    return new Response("ok");
  },
});

alreadyHandled and enqueue stand for your own storage. The verifyWebhook function is on the verify page.

Send a test event

On an endpoint's page, send a test event of any type. It carries sample data with mode set to test, data.test set to true and accountId set to null. Use it to check your signature code and your handler before real events arrive. See test events.

The signing secret

  • The secret is shown when you create the endpoint. After that, reveal it on the endpoint's page.
  • Rotate it on the same page. The new secret signs every delivery from then on and the old one stops at once. Deliveries that fail verification in between are retried on the usual schedule, so update your server promptly and nothing is lost.
  • Each endpoint has its own secret. Never reuse a secret across endpoints or put it in client code.

Deliveries

The endpoint's page lists every delivery with its status, attempts, response code and the first part of your response body. A delivery is pending, retrying, succeeded or failed. You can replay any delivery. See retries and replay.

An endpoint that fails every delivery for 5 days is turned off, with the reason shown on its page. Fix it, then turn it back on.

Events without an endpoint

Developers, then Events lists every event in your workspace, whether or not an endpoint subscribed to it. Use it to see what would have been sent, or to catch up after an outage.

On this page