Endpoint Data Sources
Where the data on each OFAPI endpoint comes from — OnlyFans, OFAPI's own database, or a mix of both.
We classify every endpoint as one of three types:
Hybrid
We make a live request to OnlyFans and then enriches the response with fields from the our database (timestamps, tags, computed classifications, etc.).
Computed
We never call OnlyFans during the request. The response is built entirely from data we have stored, synced, or calculated.
Live passthrough
Anything not listed as Hybrid or Computed. The response is straight from OnlyFans, with no enrichment.
Quick answers to common questions
GET /{account}/statistics/overview→ Live passthrough. The numbers come straight from OnlyFans.GET /{account}/fans/active→ Hybrid. OnlyFans response plus alastReplyAttimestamp on each fan, sourced from the OFAPI database.GET /{account}/transactions→ Hybrid. OnlyFans response plus a computedtypefield (subs,tips,post,chat_messages,stream).
Hybrid endpoints
These endpoints call OnlyFans live and then enrich the response with extra fields from the OFAPI database. The "Enriched with" column lists exactly what OFAPI adds on top of the OnlyFans payload.
| HTTP | Path | Enriched by OFAPI |
|---|---|---|
GET | /{account}/chats | lastReplyAt per chat |
GET | /{account}/chats/{chat_id}/messages | lastReplyAt per participant |
GET | /{account}/fans/all | lastReplyAt per fan |
GET | /{account}/fans/active | lastReplyAt per fan |
GET | /{account}/fans/expired | lastReplyAt per fan |
GET | /{account}/fans/latest | lastReplyAt per fan |
GET | /{account}/fans/top | lastReplyAt per fan |
GET | /{account}/users/{username} | lastReplyAt (if the user is a fan) |
GET | /{account}/transactions | Computed type (subs / tips / post / chat_messages / stream), derived from the OF description |
GET | /{account}/tracking-links | Tags, cached revenue & spender counts, full campaign URL prefixed with the creator's profile URL |
GET | /{account}/trial-links | Tags, cached revenue & spender counts, full campaign URL |
GET | /{account}/engagement/messages/top-message | Engagement stats joined onto the message metadata |
Computed endpoints
These endpoints never hit OnlyFans during the request. The response is built entirely from data OFAPI has stored, synced, or calculated.
Smart Links (analytics + management)
| HTTP | Path | Notes |
|---|---|---|
GET | /smart-links | List smart links |
POST | /smart-links | Create a smart link |
GET | /smart-links/{smart_link_id} | Fetch a single smart link |
DELETE | /smart-links/{smart_link_id} | Delete a smart link |
GET | /smart-links/{smart_link_id}/stats | Clicks, subs, revenue, spenders aggregated from OFAPI tables |
GET | /smart-links/{smart_link_id}/cohort-arps | ARPS by acquisition cohort |
GET | /smart-links/{smart_link_id}/fans | Attributed fans with aggregate metrics |
GET | /smart-links/{smart_link_id}/spenders | Fans where spend > 0 |
GET | /smart-links/{smart_link_id}/clicks | Raw click rows |
GET | /smart-links/{smart_link_id}/conversions | Raw conversion rows |
Stored (cache) link inventory
Explicitly free — these never call OnlyFans.
| HTTP | Path | Notes |
|---|---|---|
GET | /{account}/stored/tracking-links | Cached tracking links |
GET | /{account}/stored/trial-links | Cached free trial links |
GET | /{account}/stored/shared-tracking-links | Cached shared tracking links |
GET | /{account}/stored/shared-trial-links | Cached shared free trial links |
Webhooks
| HTTP | Path | Notes |
|---|---|---|
GET | /{account}/webhooks | List webhooks |
POST | /{account}/webhooks | Create a webhook |
GET | /{account}/webhooks/{webhook_id} | Fetch a single webhook |
PUT | /{account}/webhooks/{webhook_id} | Update a webhook |
DELETE | /{account}/webhooks/{webhook_id} | Delete a webhook |
GET | /{account}/webhooks/events | Enum of available event types |
GET | /{account}/webhooks/{webhookEventType}/example-payload | Static payload generator |
Data exports
| HTTP | Path | Notes |
|---|---|---|
GET | /data-exports | List data exports |
POST | /data-exports | Create a data export |
GET | /data-exports/{data_export_id} | Fetch a single data export |
POST | /data-exports/{data_export_id}/start | Start a data export |
DELETE | /data-exports/{data_export_id} | Delete a data export |
POST | /data-exports/{data_export_id}/retry | Retry a data export |
Link tags
Tags live entirely in the OFAPI database — none of these endpoints touch OnlyFans.
| HTTP | Path | Notes |
|---|---|---|
GET | /link-tags | List every tag in your org |
GET | /{account}/tracking-links/{tracking_link_id}/tags | List tags on a tracking link |
POST | /{account}/tracking-links/{tracking_link_id}/tags | Add tags to a tracking link |
DELETE | /{account}/tracking-links/{tracking_link_id}/tags | Remove tags from a tracking link |
GET | /{account}/trial-links/{trial_link_id}/tags | List tags on a free trial link |
POST | /{account}/trial-links/{trial_link_id}/tags | Add tags to a free trial link |
DELETE | /{account}/trial-links/{trial_link_id}/tags | Remove tags from a free trial link |
GET | /{account}/shared-tracking-links/{shared_tracking_link_id}/tags | List tags on a shared tracking link |
POST | /{account}/shared-tracking-links/{shared_tracking_link_id}/tags | Add tags to a shared tracking link |
DELETE | /{account}/shared-tracking-links/{shared_tracking_link_id}/tags | Remove tags from a shared tracking link |
GET | /{account}/shared-trial-links/{shared_trial_link_id}/tags | List tags on a shared free trial link |
POST | /{account}/shared-trial-links/{shared_trial_link_id}/tags | Add tags to a shared free trial link |
DELETE | /{account}/shared-trial-links/{shared_trial_link_id}/tags | Remove tags from a shared free trial link |
Auth & accounts
The request itself only reads or writes OFAPI rows; the actual OnlyFans login runs asynchronously in a queued job.
| HTTP | Path | Notes |
|---|---|---|
GET | /whoami | Identify the current API key |
GET | /accounts | List connected OF accounts |
DELETE | /accounts/{account} | Disconnect an OF account |
POST | /authenticate | Start an authentication attempt |
GET | /authenticate/{attempt_id} | Poll attempt status |
PUT | /authenticate/{attempt_id} | Submit credentials / 2FA |
POST | /authenticate/{attempt_id}/send-email-to-creator | Trigger the OF email-code helper |
POST | /authenticate/{account_id}/reauthenticate | Re-auth an existing account |
POST | /client-sessions | Mint a short-lived client session |
Media upload status
| HTTP | Path | Notes |
|---|---|---|
GET | /{account}/media/upload/{upload}/status | Poll an in-progress media upload |
Important clarifications
A couple of endpoints sound like they should be Hybrid or Computed, but aren't. Calling them out here to preempt confusion:
These sound calculated, but are Live passthrough
The following endpoints return numbers and metrics, but the response is a straight passthrough of what OnlyFans returns — OFAPI does not compute or enrich them:
/statistics/overview/statistics/total-transactions/statistics/subscriber-metrics/me/model-start-date/me/top-percentage/payouts/balances/payouts/eligibility/payouts/list-earning-statistics/payouts/list-payout-requests
Media URLs & file downloads
OnlyFans media files (everything served from https://cdn*.onlyfans.com/) get special handling. The first time we see a media file, we save our own copy of it; subsequent requests for that same file are served from our own CDN at https://cdn.fansapi.com/ instead of contacting OnlyFans.
Two reasons this matters for you:
- It saves credits. Once a file is cached, fetching it again does not consume any credits — OnlyFans is never contacted.
- It's significantly faster. Our CDN is geographically distributed, so cached files are served from a location close to your end users instead of round-tripping through OnlyFans every time.
This affects two kinds of endpoints.
Downloading or scraping media files
The endpoints that hand you back actual media bytes — Download Media and the deprecated Scrape Media — first check whether we already have that file in our own CDN.
- If we have it cached → you get a URL on our own
cdn.fansapi.com. Download Media returns a302redirect to it (most HTTP clients follow redirects automatically;curlneeds-L). Scrape Media returns it astemporary_urlin the response body. No credits are charged in this case, because OnlyFans is never contacted. - If we don't have it cached yet → we stream the bytes from OnlyFans straight back to you as the response, and at the same time start saving our own copy. The next time anyone asks for that same file, it will be served from our CDN.
Endpoints that return media URLs in their response
Any endpoint that returns OnlyFans CDN URLs in its response body — List Chat Messages, List Posts, List Vault Media, and so on — follows the same caching pattern, applied per-URL:
- Each
https://cdn*.onlyfans.com/*URL in the response is checked against our CDN. - URLs we already have cached are replaced with the equivalent
https://cdn.fansapi.com/*URL before the response is returned to you. - URLs we don't have cached yet are left as the original
https://cdn*.onlyfans.com/*URL, and we start saving our own copy. Future responses that include the same URL will return thecdn.fansapi.comversion instead.
This rewriting is applied per-URL, so a single response can contain any mix of OnlyFans CDN URLs and rewritten cdn.fansapi.com URLs depending on what we've already cached.
Anything not listed here
If an endpoint isn't listed on this page, treat it as a Live passthrough. The response is the OnlyFans payload, unmodified by OFAPI.