Release

September 2, 2026

Thirteen new endpoints — metadata updates, FansMetric-attributed claimers and public share links across tracking and trial links, buyer attribution for PPV mass messages — plus a trial lifecycle filter. This release contains three breaking changes, the first since dated releases began.

Current plan

Unusually for us, this release changes responses you may already be reading. Three changes are breaking: the create endpoints return a different shape, include_hidden is gone, and the stats payload lost its click fields and gained cumulative ones. Each is listed below with the exact migration. Everything else is additive.

Breaking changes

Three, all on tracking and trial links. Nothing else in the API changed meaning.

  • Create responses changed shape. POST /tracking-links and POST /trial-links used to return the raw OnlyFans object with fmTags, fmCustomSourceUrl and (for tracking) fmTrackingLinkUrl grafted on. They now return the same canonical item as the matching GET — camelCase, with nested revenue / cost / tags / links objects and every metric zeroed, because a link created a moment ago has no claims yet. If you read fmTags, read tags; if you read fmCustomSourceUrl, read customSourceUrl; fmTrackingLinkUrl is now campaignUrl.
  • include_hidden was removed. Replaced by visibility, which takes visible (the default), hidden or all. The old parameter is no longer parsed, so it is now ignored like any unknown query string — a caller still sending include_hidden=true silently gets visible-only results rather than an error. Send visibility=all to restore the previous behaviour, or visibility=hidden for the hidden-only view that was not previously possible.
  • Stats dropped clicks and gained cumulatives. summary.clicks_total and the per-bucket clicks field are gone from both stats endpoints. There was never per-day click data — for trial links the fields were always null, and for tracking links clicks_total was a lifetime counter that is still available as countTransitions on the list and get endpoints. In their place: cumulative_subs_total and cumulative_revenue_total in the summary, and cumulative_subs / cumulative_revenue on every bucket.

How the new cumulative fields window

Worth reading once before you plot them, because the date window is applied three different ways in the same response — deliberately.

  • subs_total, revenue_total and spenders_total respect date_start / date_end exactly, unchanged from before.
  • cumulative_subs_total and cumulative_revenue_total run from the link's inception to date_end and ignore date_start — a running total restarted at the window edge would not be a cumulative.
  • Buckets are sliced on whole boundaries, so a date_start in the middle of a day returns that entire day's value rather than a partial one. A consequence: the first bucket you get back can show a cumulative_revenue larger than its own revenue, because it carries pre-window activity forward.
  • Buckets are UTC and sparse — only buckets with activity are emitted, with no zero-filling. The web app buckets in the viewer's timezone and zero-fills, so comparing the two across a timezone boundary can look like a one-day shift.
  • On an unwindowed call, subs_total == cumulative_subs_total and the last daily bucket's cumulative_revenue equals cumulative_revenue_total. Handy as a self-check.

New endpoints

Thirteen. Twelve are on tracking and trial links — six per type, all FansMetric-backed and badged FM — plus one live OnlyFans relay on mass messages.

  • Metadata updates. Update Tracking Link and Update Trial Link partially update the five FansMetric-side fields — custom_name, note, custom_source_url, promo_cost and is_hidden — without touching OnlyFans. Merge-patch: an absent key is left alone, an explicit null clears the column, a value is validated and set. is_hidden is the one field that cannot be null.
  • FansMetric-attributed claimers. Tracking and trial — the data behind the web app's Claims modal.
  • Public share links. List, create, update and delete for tracking links and trial links. The share's UUID is the public token, and the response hands you the ready-to-send URL — do not assemble it yourself, because the origin differs per deployment. Delete is a hard delete: the page 404s immediately and the token cannot be revived.
  • Mass-message buyer attribution. List Mass Message Buyers returns the fans who purchased a specific PPV mass message — the drill-down behind a queue row. Mass Message Statistics reports sentCount and viewedCount but carries no purchaser attribution; this is where it lives. Only meaningful for paid sends — a free message returns an empty list. Rows are ID-only stubs, so hydrate with Get Fan Details; pagination is offset-based with a marker snapshot pin, the same scheme as List Payout Requests.
  • New permissions accompany these: api_{tracking,trial}_links_update, api_{tracking,trial}_links_{list_shares,create_share,update_share,delete_share}, and api_mass_messages_list_buyers for the buyers endpoint. The claimers endpoints reuse the existing api_tracking_links_list_claimers and api_trial_links_list_subscribers. A role missing a permission returns 403, so grant them before switching traffic over.

Smaller additions

Additive; nothing to migrate.

  • visibility on both FansMetric lists. visible (default), hidden or all. The hidden value is new capability — previously there was no way to ask for only hidden links.
  • status on the trial list. all (the default, so existing calls are unaffected), active or finished. This is the trial analogue of tracking links' with_deleted: OnlyFans finishes trials rather than deleting them, so isFinished — not a date — is the lifecycle signal. visibility and status combine freely.
  • Sorting the FansMetric lists by claim count without a date window is now materially faster on large accounts. No API change; the same request just returns sooner.

Docs corrections

Two claims on Earnings Overview were corrected against captured traffic. The API did not change — the page did.

  • by takes messages, not massMessages — that is the response key, not the input value. The page now notes where the by vocabulary and the response keys diverge.
  • chartData bucket granularity is window-dependent, not fixed monthly — a 90-day window returns daily buckets. Read each point's date rather than assuming a period.