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

# Insights metrics: payment sources, gross vs net, reversals

> What each payment source means, which insights figures are gross and which are net of refunds and chargebacks, and how reversals are recorded.

The insights and earnings endpoints report money in a few different ways, and the differences are not guessable from the field names. This page is the reference for three things integrators keep having to ask about: what each payment `source` actually covers, which figures are gross and which are net of refunds and chargebacks, and how a reversal is recorded.

## Payment sources

Every earning row on [`GET /insights/earnings`](/docs/api-reference/get-earnings-data) carries a `source`, and the fan spend breakdown on [`GET /insights/fans/{userUuid}`](/docs/api-reference/get-fan-insights) is keyed by the same names.

| `source`        | What it is                                                                                                | Fan pays the creator?                           | Recurring charges land on |
| --------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------- |
| `subscription`  | The payment that starts a profile subscription                                                            | Yes                                             | `renewal`                 |
| `renewal`       | Every recurring charge after a first payment, whatever started it                                         | Yes                                             | `renewal`                 |
| `message`       | A fan unlocking a paid (PPV) chat message                                                                 | Yes                                             | Not recurring             |
| `post`          | A fan unlocking a paid post                                                                               | Yes                                             | Not recurring             |
| `tip`           | A tip, sent on a post or in a chat                                                                        | Yes                                             | Not recurring             |
| `mediaLink`     | A fan buying a media link                                                                                 | Yes                                             | Not recurring             |
| `checkoutLink`  | A fan's first payment on a checkout link, one-time or subscription                                        | Yes                                             | `renewal`                 |
| `fanExperience` | A fan buying a creator's paid experience: a one-off unlock, or the first charge of a recurring experience | Yes                                             | `renewal`                 |
| `appStore`      | The creator buying a third-party app, one-off or subscription                                             | No, this is the creator paying an app developer | `appStore`                |
| `referral`      | A Fanvue referral reward                                                                                  | No fan involved, `user` is `null`               | Not recurring             |
| `affiliate`     | An affiliate reward                                                                                       | No fan involved, `user` is `null`               | Not recurring             |
| `giveaway`      | Promotional credit Fanvue posts to the creator                                                            | No fan involved, `user` is `null`               | Not recurring             |
| `refund`        | A refund of an earlier payment, with negative `gross`/`net`                                               | Reverses a fan payment                          | Mirrors the original      |
| `chargeback`    | A chargeback on an earlier payment, with negative `gross`/`net`                                           | Reverses a fan payment                          | Mirrors the original      |

## The `renewal` catch-all

`renewal` is not "subscription renewal". It is **every recurring charge after the first payment**, no matter which product started the subscription: profile subscriptions, checkout-link subscriptions and recurring fan experiences all bill as `renewal` from their second charge onwards.

`appStore` is the single exception. An app subscription's recurring charges stay under `appStore`.

The consequence catches integrators out. A fan subscribes to a recurring fan experience priced at 500 cents per month:

| Charge                      | `source`        |
| --------------------------- | --------------- |
| Month 1, the fan subscribes | `fanExperience` |
| Month 2, automatic renewal  | `renewal`       |
| Month 3, automatic renewal  | `renewal`       |

So `fanExperience` only ever holds first payments and one-off unlocks, and the same is true of `subscription` and `checkoutLink`. If you want a product's full recurring revenue you cannot read it off one `source`: `renewal` is where the ongoing money is, and it does not say which product produced it.

<Note>
  A `renewal` row does not tell you which product renewed. To attribute renewals
  to a product, follow the fan's subscription rather than the earning source.
</Note>

## Fan experiences and the App Store are different transactions

Both involve a third-party app, and the same app can produce both, but the parties are different:

* **`fanExperience`** is the **creator selling to a fan**. An experience is a fan-facing mini-app the creator publishes, backed by a third-party app. This is fan-to-creator spend and it belongs in fan spend metrics.
* **`appStore`** is the **app developer selling to the creator**. The buyer is the creator who installs the app. A fan cannot even see the App Store, so an `appStore` invoice is not fan spend on a creator.

Only **paid** experiences produce a payment. A free experience produces no invoice of any kind, so it never appears on any earnings or spend figure.

<Warning>
  Fan experiences are not fully live yet. They are behind a staged rollout, so
  most creators will have no `fanExperience` rows at all today.
</Warning>

## Gross, net, and reversals

Two different distinctions share the words gross and net, and the endpoint decides which one is meant:

* **The fee axis.** On the earnings endpoints and the agency insights endpoints, `gross` is what the fan paid and `net` is the creator's cut after platform fees. Both describe the same transaction.
* **The reversal axis.** Whether a refunded or charged-back purchase is still counted. This is per field, and it is **not** consistent across the insights surface.

The table below is the reversal axis, field by field.

| Endpoint and field                                          | Reversal treatment                                                                                                                                        |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /insights/earnings` rows                               | Reversals are their own `refund`/`chargeback` rows carrying negative amounts. Original payment rows are never rewritten.                                  |
| `GET /insights/earnings/summary`                            | Reversals are left out of every figure rather than subtracted, on both `gross` and `net`.                                                                 |
| `GET /insights/spending`                                    | Reversal rows only, this endpoint returns nothing else.                                                                                                   |
| `GET /insights/top-spenders` `gross`/`net`                  | **Gross of reversals.** Only positive invoices are counted, so a refunded purchase stays in at its full amount.                                           |
| `GET /insights/fans/{userUuid}` `spending.total`            | **Net of reversals.** Each refund or chargeback is subtracted, so the figure can be lower than the sum of the sources, and can even be negative.          |
| `GET /insights/fans/{userUuid}` `spending.sources.*`        | **Gross of reversals.** A reversed purchase is still counted in full, and reversals are not returned as a source of their own.                            |
| `GET /insights/fans/{userUuid}` `spending.maxSinglePayment` | **Excludes reversed purchases.** A payment later refunded or charged back is not eligible to be the highest. This has been the behaviour since July 2025. |
| `GET /insights/fans/{userUuid}` `spending.lastPurchaseAt`   | Fan-initiated payments only, so an automatic renewal never moves it. Reversed purchases are **not** skipped: the fan did buy at that moment.              |
| `GET /agencies/insights/*` `gross`/`net`                    | Both are already net of refunds and chargebacks. Here `gross` and `net` are the fee axis only.                                                            |

### Why the sources do not add up to the total

On `GET /insights/fans/{userUuid}`, `spending.total` is net of reversals while `spending.sources` are gross of them. The two therefore disagree, and the gap is exactly the reversals, which are dropped from `sources` entirely rather than shown as their own entry.

If you need the two to reconcile, fetch the fan's reversals from [`GET /insights/spending`](/docs/api-reference/get-spending-reversal-data) with `fanUuid` set and subtract them yourself.

<Note>
  Fanvue is adding reversal-free companions to `spending.total`, to each
  per-source figure and its average, and a last-valid-purchase field alongside
  `spending.lastPurchaseAt`. The existing fields keep their current meaning, so
  nothing shifts under an integration that already reads them. Separately,
  Fanvue is removing `appStore` from the fan spend metrics as a correction,
  because it records a creator's purchase from an app developer rather than a
  fan's spend. That one does move numbers, and the [changelog](/docs/changelog) will
  call it out when it ships.
</Note>

## How a reversal is recorded

A refund or a chargeback is written as **its own invoice**, never as an edit to the payment it reverses. Three consequences worth knowing:

1. **The original stays settled.** It keeps its own row on `GET /insights/earnings` with its original amount. Nothing about it changes when it is reversed.
2. **A reversal is always the full amount.** Fanvue has no partial refunds, so a reversed purchase is reversed for exactly what the fan paid.
3. **The pairing is explicit.** On `GET /insights/earnings`, `refund` and `chargeback` rows carry `reversedTransactionOrderId`, which is the `transactionOrderId` of the payment they reverse. That is the supported way to match the two.

```json theme={null}
{
  "data": [
    {
      "date": "2026-08-14T09:12:00Z",
      "gross": -1999,
      "net": -1799,
      "currency": "USD",
      "source": "refund",
      "transactionOrderId": "FVC-20260814-91",
      "transactionOrderStatus": "availableForPayout",
      "reversedTransactionOrderId": "FVE-20260801-44"
    },
    {
      "date": "2026-08-01T16:40:00Z",
      "gross": 1999,
      "net": 1799,
      "currency": "USD",
      "source": "message",
      "transactionOrderId": "FVE-20260801-44",
      "transactionOrderStatus": "availableForPayout"
    }
  ],
  "nextCursor": null
}
```

Both rows also carry the fan's `user` object, trimmed here for brevity. Note that the original `message` row is untouched: it still reports the full 1999 it was paid.

## Freshness

| Endpoint                                                                           | Freshness                                                                                                                                                                                                                                                                                                                                     |
| ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /insights/fans/{userUuid}`, `GET /insights/fans`, `POST /insights/fans/batch` | Computed from live invoice data on every request, with no caching. Two reads seconds apart can legitimately return different numbers.                                                                                                                                                                                                         |
| `GET /insights/earnings/summary`                                                   | Cached for up to 10 minutes per creator and per parameter set, so a figure can lag a payment that has already settled.                                                                                                                                                                                                                        |
| `GET /agencies/insights/*`                                                         | Whole UTC days come from the daily warehouse export; the current day, and any partial day at either edge of the range, are read live from invoices. The `overview` endpoint's `retention` and `averageFanLifetime` are the exception: they are warehouse snapshots with no live branch, and are not affected by `startDate`/`endDate` at all. |

## Agency insights

Three agency-level insights endpoints sit alongside the chatter leaderboard, under **Agency Insights** in the [API Reference](/docs/api-reference/overview). All of them are agency-wide: they aggregate across every creator the agency manages, and accept a `creatorUuids` filter (max 50) to narrow to a subset.

| Endpoint                              | Returns                                                                                                                                       | Scopes                                    | Pagination                |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------------------------- |
| `GET /agencies/insights/overview`     | Headline metrics: total earnings, newly acquired fans, average revenue per paying fan, the 30-day retention snapshot and average fan lifetime | `read:agency`, `read:creator`             | None, single object       |
| `GET /agencies/insights/demographics` | Paying fans grouped by billing country, ordered by fan count descending                                                                       | `read:agency`, `read:creator`             | Cursor, pass `nextCursor` |
| `GET /agencies/insights/top-fans`     | The five highest-spending fans across the agency's creators                                                                                   | `read:agency`, `read:creator`, `read:fan` | None, at most five rows   |

Every row returns **both** figures, `gross` and `net`, so you never have to pick one at request time. On `top-fans`, `earningsView` chooses which of the two the ranking is done by, and both are returned regardless. Amounts are USD cents.

This gross-and-net-on-every-row shape is the convention the fan insights endpoints are moving to as well.

<Note>
  Agency endpoints require agency admin access on top of the scopes above. A
  `creatorUuids` value that does not belong to the agency fails the whole
  request with `403` rather than being ignored.
</Note>
