Send your key as a bearer token in the Authorization header. The x-api-key header works too. Keys that start with bfl_live_ read linked accounts; keys that start with bfl_test_ read the sandbox creators. See keys and scopes.
synced for synced data, live for a read straight from OnlyFans, sandbox in test mode. One of synced, live or sandbox.
asOf
timestamp or null
When the data was last synced from OnlyFans; null for live reads.
requestId
string
The request id, also sent in the x-request-id response header.
sideEffects
array of enums
Optional. Present only when a live read changed something on OnlyFans. thread_marked_read means a fresh=true chat read could not restore the unread state. Each one of thread_marked_read.
Routes that take cursor and limit return one page at a time. limit is 25 by default. A limit above 100 is treated as 100; a limit below 1, or one that is not a whole number, is invalid_parameter. Pass nextCursor back as cursor until hasMore is false. A cursor belongs to one list with one set of filters: keep the other parameters the same while you page.
async function allFans(accountId: string) { const fans = []; let cursor: string | null = null; do { const url = new URL(`https://app.betterfans.link/v1/accounts/${accountId}/fans`); url.searchParams.set("limit", "100"); if (cursor) url.searchParams.set("cursor", cursor); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.BFL_KEY}` } }); const body = await res.json(); if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`); fans.push(...body.data); cursor = body.hasMore ? body.nextCursor : null; } while (cursor); return fans;}
Ids are strings, even when they look like numbers. An account id is the creator's OnlyFans user id; a fan id is the fan's OnlyFans user id and also the chat id.
Timestamps are ISO 8601 strings in UTC. from and to take a date (2026-09-01) or a timestamp.
Money is an object with integer cents and a currency. See money.
Unknown query parameters are ignored. A known parameter with a bad value is invalid_parameter.
Every response has an x-request-id header. Errors repeat it as requestId.
Errors come back with an HTTP status and a JSON body with a stable error.code. Every route can also return the authentication errors, rate_limited and internal_error. Each route lists its own errors. The errors page explains every code.