BetterFans Link SDK — OnlyFans APIBetterFans Link SDK
HTTP Client

Making requests

Use the typed request methods to call any OnlyFans API route.

The SDK provides two patterns for making requests: a tuple pattern that returns [error, data] for explicit error handling, and a throw pattern that throws on failure.

The tuple pattern: request()

request() returns a tuple of [error, null] or [null, data]. This makes error handling explicit without try/catch:

const account = client.for("123456789")

const [error, data] = await account.request("GET /users/me", {})

if (error) {
  console.error(error.code, error.status, error.message)
} else {
  console.log(data.name) // fully typed as UserFull
}

The first argument is always a route string in the format "METHOD /path". TypeScript narrows the parameters and response based on this string.

The throw pattern: fetch()

If you prefer exceptions, fetch() has the same signature but throws an OfApiError on failure:

try {
  const me = await client.fetch("GET /users/me", {
    auth: { onlyfansUserId: "123456789" },
  })
  console.log(me.name)
} catch (error) {
  if (error instanceof OfApiError) {
    console.error(error.code, error.status)
  }
}

Verb shortcuts

For ergonomics, the client exposes .GET(), .POST(), .PUT(), and .DELETE() methods. These are sugar over request() with the verb extracted from the path:

const [error, chats] = await client.GET("/chats", {
  auth: { onlyfansUserId: "123456789" },
  query: { limit: 20 },
})

Request options

Every request accepts these options:

Prop

Type

Route string format

Routes follow the pattern "VERB /path" exactly as they appear in the OnlyFans API. Path parameters use :name syntax:

// No parameters
"GET /users/me"

// Path parameter
"GET /users/:id"
"DELETE /posts/:id"

// Multiple path parameters
"POST /lists/:id/users/:id"

TypeScript infers the required pathParams, query, and body from the route string. If you misspell a route, you get a compile error — not a runtime 404.

Type inference

You can extract input and output types for any route using the ApiRoutes interface:

import type { ApiRoutes } from "@betterfans/link-sdk"

type ChatsQuery = ApiRoutes["GET /chats"]["query"]
// { limit?: number; offset?: number; order?: string; ... }

type ChatsResponse = ApiRoutes["GET /chats"]["response"]
// { list: ChatListItem[]; hasMore: boolean; ... }

type SendBody = ApiRoutes["POST /chats/:id/messages"]["body"]
// { text?: string; mediaFiles?: ...; price?: number; ... }

This is useful for building typed wrappers or passing data between functions without losing type information.

On this page