# OF and Fansly profitability

Updated 2026-10-09. These are implemented reporting and input-storage endpoints, not native proxy aliases.
Use `https://api.creator-api.com` with `X-API-Key: YOUR_KEY`.
OnlyFans and Fansly are supported. Fanvue is not enabled for this feature.

## Read a month

`GET /v1/{account}/analytics/profitability?year=2026&month=8`

`{account}` is the connected CreatorAPI account ID. Years: 2000–2100; months: 1–12.
Future reporting months are rejected. All periods use UTC, with an exclusive end.
The current month covers only observed activity up to `asOf`; it is not a forecast.

A collection may first return HTTP 202:

```json
{"data":{"status":"collecting","job_id":"prf_example","poll_after_seconds":2}}
```

Repeat the same request after `Retry-After: 2` until HTTP 200. Do not substitute an export-job URL:
this is an in-memory read snapshot, not an export. Identical requests share one scan for five minutes,
scoped to the workspace and exact input snapshot. Restarting the service can require a fresh scan.
Responses use `Cache-Control: no-store`.

Completed example, using synthetic values:

```json
{
  "data": {
    "account": "YOUR_ACCOUNT",
    "platform": "onlyfans",
    "year": 2026,
    "month": 8,
    "currency": "USD",
    "actualNet": "10000.00",
    "projectedNet": null,
    "commissionRate": "20",
    "commissionAmount": "2000.00",
    "agencyEarnings": "2000.00",
    "costs": [{"label": "Operations", "amount": "500.00"}],
    "totalCosts": "500.00",
    "profit": "1500.00",
    "marginPercentage": "75.00",
    "hasCommissionForPeriod": true,
    "hasCostsForPeriod": true,
    "ratePeriods": [],
    "periodComplete": true,
    "unsupportedFeatures": ["forecasts", "milestones", "referrals"]
  }
}
```

The actual response also includes `asOf`, `configurationRevision`, source coverage/request counts,
and top-level `meta` with cache identity and `billable: false`.
Money and percentages are decimal strings, not binary floating-point amounts.
No real commission or cost data is inferred from a creator's account.

## Provide commission and costs

`GET /v1/{account}/analytics/profitability/config/{year}/{month}` reads inputs.

`PUT /v1/{account}/analytics/profitability/config/{year}/{month}` replaces that month's entire input object:

```json
{
  "currency": "USD",
  "commission_rate": "20",
  "costs": [{"label": "Operations", "amount": "500.00"}]
}
```

Alternatively provide non-overlapping inclusive day ranges instead of `commission_rate`:

```json
{
  "rate_periods": [
    {"start_day": 1, "end_day": 15, "rate": "15"},
    {"start_day": 16, "end_day": 31, "rate": "20"}
  ],
  "costs": []
}
```

Rates must be 0–100, with at most six decimal places. Ranges must fit the calendar month.
Every elapsed day needs a rate, including days without earnings. A single rate covers the whole month.
Costs are nonnegative USD cents, at most 200 labeled entries. Unknown fields, overlapping ranges,
and mixing a constant rate with ranges are rejected.

Omitted or null `costs` means unknown; `costs: []` explicitly means zero costs.
Omitted or null commission means unknown unless the rate ranges cover the period.
Missing inputs yield null commission/profit/margin rather than invented zeros.
Costs apply in full to the selected month; no hidden proration occurs for a partial current month.

`DELETE /v1/{account}/analytics/profitability/config/{year}/{month}` removes exactly that workspace,
account and month's stored inputs, returning `deleted: true` or `false`. It never deletes a payment.

Inputs are project-local CreatorAPI settings, separate from the shared original-project data.
PUT and DELETE require a full-scope key and, for staff, `analytics.manage`.
Reads require account scope, an active creator slot, platform access and staff `analytics.view`.
Input changes invalidate the calculation cache; each report uses one immutable input snapshot.

## Batch and history

`POST /api/analytics/financial/profitability` is a read-only batch calculation:

```json
{"account_ids":["YOUR_OF_ACCOUNT","YOUR_FANSLY_ACCOUNT"],"year":2026,"month":8}
```

It accepts 1–20 account IDs, deduplicates them and authorizes every account before reading any provider.
The completed `data` is an array. Readonly keys and staff with `analytics.view` can use this POST.

`GET /v1/{account}/analytics/profitability/history?months=12`

`GET /api/analytics/financial/profitability/{account}/history?months=12&account_prefixed_id={account}`

History includes the current month, newest first; `months` is 1–60. The optional
`account_prefixed_id` must equal the path account. Completed `data` is an array.
Batch and history use the same 202 polling convention as a monthly read.

## Financial basis and safety

OnlyFans: explicit signed native `net` in the transaction ledger, plus the chargeback feed.
A reversal appearing in both is counted once; amounts and UTC date must agree.
Chargebacks are attributed to the reversal day, not the original sale day.
Currency, identity, date ordering and continuation markers are validated.

Fansly: the earnings-only transaction feed's `destinationAmount / 1000`, reconciled exactly
against daily native earnings `totalNet / 1000` by day and transaction type.
No guessed platform fee and no wallet-balance subtraction. Withdrawals are not income.
Only the supported earnings destination and observed pending/settled status shapes are accepted.
Missing net values, unrecognized wallet/status shapes, changed pagination totals or disagreement
between ledger and earnings stats fail the report. A provider settlement lag can therefore require a retry.
These figures are earnings, not necessarily cash available for payout.

Commission is the sum of each day's net earnings multiplied by its applicable rate, rounded once to cents.
Profit is rounded commission minus the explicitly supplied costs.
Margin is profit divided by commission times 100, only when commission is positive;
otherwise margin is null. Negative earnings and signed reversals reduce the commission basis.

There are two concurrent readers globally, 32 cached reports, at most 240 native requests and
200 pages per source, an 8 MiB decoded page budget, and a five-minute scan budget checked around reads.
Transport timeouts are bounded per request but these are not atomic provider snapshots or hard network deadlines.
Busy/exhausted capacity returns 503; invalid/inconsistent source data returns 502 without partial totals.
Narrow the period or batch when limits are reached. Native data retention still limits coverage.
These service routes currently charge zero API credits; directly calling native routes retains native-read pricing.

## Verification and comparison boundary

Local arithmetic, input persistence, authorization, asynchronous HTTP and failure tests are separate from live proof.
Bounded live reads were verified for an OF current-month ledger/chargeback window and Fansly's August earnings.
An isolated Fansly calculation used explicitly synthetic commission/cost inputs; those inputs were removed.
No message, purchase, payout or native account setting was changed by these checks.

The reference profitability route shapes are supported, but this is not full response-equivalence with
OnlyFansAPI. CreatorAPI returns its own account ID, explicit `actualNet`, decimal strings and source evidence.
It does not invent `onlyFansUserId` or `creatorName` fields. Forecasts, milestone configuration and referral
commission rules are not implemented; `projectedNet` stays null. No complete feature parity or complete
live verification is claimed.

