ofapisv1
capability

Updated

OnlyFans Tracking Links & Attribution

ofapis has no tracking-links endpoint. It cannot mint an OnlyFans tracking link, read the click counts behind one, or tell you which link a fan arrived through. No route on this API accepts or returns a referrer, a campaign tag, or a source of any kind.

What you can do is measure a bounded window around one promotion: establish what the account looked like immediately before the push, run the push, read the account again immediately after, and treat the difference as that push's effect. This page is about doing that honestly — the procedure, and the precise list of things it cannot tell you.

The measurement, not the metric

A growth dashboard asks "how is the audience trending" and answers from a regular snapshot cadence. Attribution asks "what did this post at this hour do" and answers from two reads placed deliberately around one event. Same primitive, opposite shape: the cadence job runs forever at a fixed interval and ignores events, the attribution job runs twice around one event and ignores the long run. Keep them as separate code paths, because a nightly cadence job is far too coarse to resolve a 90-minute Reddit push — that is the job on the statistics API page, not this one.

Procedure

  1. Quiet period. Schedule the promo where nothing else is running: no mass DM, no PPV drop, no second channel going out. Confounders are the main error term here and this is the only place you control them.
  2. Baseline, t−0. Read the active subscriber id set and the counters right before the link goes live.
  3. Push. Post the link.
  4. Close, t+N. Read the same things again after the window closes.
  5. Diff. The ids present at close and absent at baseline are the new fans in that window.

capture.sh takes one reading, in plain curl and jq. Run it before the push and again after the window closes.

#!/usr/bin/env bash
set -euo pipefail
B=https://api.ofapis.com/api/public/v1
A=${1:?accountId}; TAG=${2:?baseline|close}
H="Authorization: Bearer ${OFAPIS_TOKEN}"
off=0; : > "ids.${TAG}"

while :; do                                  ## active ids, 100 per page
  page=$(curl -sf -H "$H" "$B/accounts/$A/subscribers?type=active&limit=100&offset=$off")
  jq -r '.data.list[].id' <<<"$page" >> "ids.${TAG}"
  [ "$(jq -r '.data.hasMore' <<<"$page")" = true ] || break
  off=$((off + 100))
done

curl -sf -H "$H" "$B/accounts/$A/notifications/count" \
  | jq --arg t "$(date -u +%FT%TZ)" '{at:$t, newCount:.data.newCount}' > "count.${TAG}"

Then the fans gained during the window, by id:

comm -13 <(sort -u ids.baseline) <(sort -u ids.close)

That comm output is the real deliverable, and it is better than a number: you get the identities, so you can greet those specific fans, drop them into a fan list, or follow what they go on to spend. A click counter in a URL shortener cannot do that. Pair the two and you have clicks on one side and named conversions on the other, which is as close to end-to-end as this gets.

What the window actually costs

One credit per call. The sweep is ceil(fans / 100) calls, run twice, plus two counter reads.

Audience Credits per campaign reading Both readings
1,000 11 22
10,000 101 202
50,000 501 1,002

Rate limits bite here in a way they never do on a slow cadence job, because both readings are bursts and the second one is time-critical. A 50,000-fan sweep is 501 requests: at Free's 60 rpm that is over eight minutes of wall clock, wider than some promo windows and far past Free's 250 monthly credits anyway. Starter's 100 rpm takes five minutes, Pro's 500 rpm about one. If your close reading takes longer than the window you are measuring, the measurement is meaningless — size the audience against the plan before you plan the campaign. The window mechanics are on rate limits.

For a large roster, measure with /me's subscribersCount instead: two calls, two credits, and the answer is a count rather than a set of names. Lower resolution, instant readings.

What this cannot tell you

Be specific with clients about this list, because every item is a way the number can be wrong.

You want You get Why
Which link a fan used Nothing No referrer or source field exists on any response
Per-link conversion rate Clicks from your shortener, conversions from the window The two sides never join on a key
Two campaigns at once One blended number Windows overlap, and nothing separates them
Conversions after the window Nothing A fan who converts next Tuesday lands in no window
Organic baseline Nothing automatic You must measure a control window yourself

The last one is the one teams skip and should not. Run the same capture over a comparable quiet window with no promo in it and you get the account's background join rate. Subtract it. Without that subtraction you are crediting the channel with fans who would have joined anyway, and on a large account that background rate can be most of what you measured.

Two more practical traps. Lapses move the count in the opposite direction, so always diff id sets, not counts — a window with 12 joins and 9 lapses reads as +3 and you will under-report the channel by 75%. And /notifications has no offset and a hard ceiling of 100 items, so in a busy window the overflow is lost; the counter from /notifications/count is a level, not a per-window tally. Treat it as corroboration that something happened, not as the measurement — the notifications API page explains why.

What an attribution endpoint would need

Worth stating plainly, because it is what to ask for. Real attribution needs a source token that survives the hop to OnlyFans, a per-subscriber field recording which token the fan arrived with, and a read route that aggregates by token. None of the three exists in the OnlyFans surface ofapis wraps, so ofapis cannot synthesise them.

The usable half is the click layer you own: a distinct shortener URL per channel gives reliable click counts, which tell you what drives traffic even when they cannot tell you what converts. Pair those with named conversions per window, and roll the per-campaign results into whatever agency automation runs your weekly summaries.

FAQ

No. There is no endpoint that creates, lists or reads OnlyFans' native tracking links, and none is implied by any other route. Use your own shortener or UTM-tagged landing page for the click side and measure the conversion side with the windowed diff above.

How long should the measurement window be?

Long enough to catch the conversion lag of the channel and short enough to exclude the next thing you do. A Reddit or X push converts mostly within a couple of hours, so two to four hours is typical; a shoutout in a creator's DMs can run a day. Fix the length before you start, because choosing it after seeing the data is how you talk yourself into a good result.

What happens if two promotions overlap?

You get one blended number and no way to split it, because nothing in the data identifies a source. If you must run both, stagger them so each has a clean window, or accept the combined figure and label it as combined rather than attributing it to the louder channel.

Not from the API. The closest you get is the id set that appeared during one channel's exclusive window, which is a strong inference when the window is genuinely exclusive and worthless when it is not. Those ids are real and usable — push them into a list and fire a channel-specific welcome sequence at them through the messaging API.

Does measuring a campaign cost credits?

Yes, one per successful call, and a full before-and-after sweep of a 50,000-fan account is about 1,002 credits. A 429 is refused before metering and is free, 424 and 5xx are refunded, but 400 and 404 are charged and not refunded. See pricing for allowances.

Get a token free · Full API reference

Related guides

All guides
Start free — 250 credits, no card
Generate a token and make your first call in minutes.
Get started