> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ofauth.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Calling Access

> Call typed OnlyFans operations with a bearer token and a linked account id

Access operations live under `/v3/access/*`. Every operation is typed and mapped to one scope. There is no raw proxy in V3.

## Headers

| Header | Value |
| - | - |
| `Authorization` | `Bearer <access_token>` from the [token endpoint](/v3/tokens). |
| `x-linked-account-id` | A [linked account id](/v3/linked-accounts) of this authorization. |
| `Content-Type` | `application/json` for request bodies. |

API keys are rejected. A request with `apikey` or `x-api-key`, or without a bearer, returns `401 external_oauth_bearer_required`.

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.ofauth.com/v3/access/profile \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "x-linked-account-id: conn_example123"
  ```

  ```javascript Node.js theme={null}
  async function access(userId, linkedAccountId, path, init = {}) {
    const accessToken = await getFreshAccessToken(userId) // refresh when < 60s left
    const response = await fetch(`https://api.ofauth.com/v3/access${path}`, {
      ...init,
      headers: {
        authorization: `Bearer ${accessToken}`,
        "x-linked-account-id": linkedAccountId,
        "content-type": "application/json",
        ...init.headers
      }
    })
    if (!response.ok) {
      const body = await response.json()
      throw new AccessError(response.status, body.error, body.recovery?.action, body.requestId)
    }
    return response.json()
  }

  const profile = await access(userId, linkedAccountId, "/profile")
  const chats = await access(userId, linkedAccountId, "/chats?limit=20")
  await access(userId, linkedAccountId, "/chats/12345/messages", {
    method: "POST",
    body: JSON.stringify({ text: "Hello" })
  })
  ```
</CodeGroup>

Every response carries `x-request-id`. Include it in support requests.

## Scopes

Request only the scopes you need. The user sees each scope on the consent screen. `offline_access` is the only non-Access scope; it controls refresh tokens.

| Scope | Grants |
| - | - |
| `profile:read` | Read the profile, counts, links, settings, release forms. |
| `profile:write` | Update the profile, links, social buttons, settings, release forms. |
| `notifications:read` | Read notifications and unread counts. |
| `notifications:write` | Mark notifications as read. |
| `posts:read` | Read posts, comments, buyers, tips, bookmarks. |
| `posts:write` | Create, edit, delete, pin, archive posts; manage comments and bookmarks. |
| `stories:read` | Read stories, highlights, viewers, stats. |
| `stories:write` | Create and delete stories and highlights; like, watch, block. |
| `queue:read` | Read scheduled posts, messages, and saved-for-later items. |
| `queue:write` | Publish or delete queued items. |
| `messages:read` | Read chats, messages, chat media, mass messages, templates. |
| `messages:write` | Send, delete, pin, like messages; mute or hide chats; send mass messages. |
| `subscribers:read` | Read subscribers, activity, awards, subscription history. |
| `subscribers:write` | Set notes, display names, and discounts for subscribers. |
| `subscriptions:read` | Read the accounts this user subscribes to. |
| `subscriptions:write` | Subscribe and hide or show posts from subscriptions. |
| `users:read` | Look up users, search, friends, blocked and restricted lists. |
| `users:write` | Block, unblock, restrict, unrestrict users. |
| `lists:read` | Read user lists, fans and following lists, labels. |
| `lists:write` | Create, edit, sort, delete lists; add or remove members; manage labels. |
| `promotions:read` | Read promotions, bundles, offers, tracking links, trial links. |
| `promotions:write` | Create, end, delete promotions, bundles, tracking links, trial links. |
| `analytics:read` | Read profile, post, story, stream, message, promotion, and traffic analytics. |
| `finances:read` | Read earnings, transactions, chargebacks, payouts, referrals. |
| `vault:read` | Read vault media and vault lists. |
| `vault:write` | Upload media; create, edit, delete vault lists; hide media. |

The full scope to operation table is generated from the API catalog. Each operation's reference page shows its scope. The discovery document lists every supported scope in `scopes_supported`.

## Environments and quotas

| Environment | Data | Limits |
| - | - | - |
| Sandbox | Mock. No OnlyFans calls. | Standard rate limits. |
| Test | The integration owner's designated test accounts. | Standard rate limits plus a daily operation quota. |
| Live | Real customer accounts. | Standard rate limits. Requires Developer plan and Live approval. |

When the Test quota is used up, calls return `429 quota_exhausted` with `Retry-After` set to the seconds until the UTC reset.

## Rate limiting

Each authorization can make 600 requests per minute across `/v3/access`, `/v3/vault-plus`, and `/v3/linked-accounts`, with short bursts allowed. Responses carry `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`. Above the limit, calls return `429` `rate_limited` with `recovery.action` `retry`. Back off until `RateLimit-Reset` and retry.

## Media

Media URLs in responses are proxied through `media.ofauth.com` and are safe to embed. They expire; re-read the parent resource to get a fresh URL. See [Media](/guides/media) for formats and the [Vault+](/v3/vault-plus) page for persistent storage.

## Error handling

Every error has the shape `{ error, recovery: { action }, requestId }`. Branch on `recovery.action`, not on HTTP status alone. See [Errors](/v3/errors) for the full list.

```javascript Node.js theme={null}
try {
  return await access(userId, linkedAccountId, "/profile")
} catch (err) {
  switch (err.recovery) {
    case "obtain_external_oauth_token":
      await refreshTokens(userId); return retry()
    case "reconnect_linked_account":
      return askOwnerToReconnect(linkedAccountId)
    case "request_additional_consent":
    case "grant_linked_account":
      return startAuthorization(userId, { scope: requiredScopes })
    case "restart_authorization":
      return startAuthorization(userId)
    case "retry_after_reset":
    case "retry":
      return scheduleRetry(err)
    default:
      throw err
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.