> ## 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.

# App events

> Events Fanvue sends your app about its own sales and experience charges: payments, subscriptions, refunds, disputes and priced actions.

`app.*` events tell your app about its own [App Store billing](/docs/payments/app-billing/overview) and about priced actions fans buy inside its experiences. They reach your app only, and you can't subscribe to them through `POST /webhooks/subscriptions`.

You need `read:self` on your app, a destination in the **Events** tab or your App Manifest, and a receiver that [verifies `X-Fanvue-Signature`](/docs/webhooks/signature-verification) against the raw body before it parses JSON.

## Available events

| Event (`type`) | `data.object` | Fires when | Reference |
| - | - | - | - |
| `app.payment.pending` | `payment` | A charge is created and awaiting confirmation | [App events: payments](/docs/webhooks/app/payments) |
| `app.payment.succeeded` | `payment` | A charge succeeds | [App events: payments](/docs/webhooks/app/payments) |
| `app.payment.failed` | `payment` | A charge fails | [App events: payments](/docs/webhooks/app/payments) |
| `app.subscription.activated` | `subscription` | A subscription becomes active | [App events: subscriptions](/docs/webhooks/app/subscriptions) |
| `app.subscription.cancel_at_period_end_changed` | `subscription` | Auto-renew is turned off; access continues to period end | [App events: subscriptions](/docs/webhooks/app/subscriptions) |
| `app.refund.created` | `refund` | A one-time purchase is refunded, charged back or cancelled | [App events: refunds and disputes](/docs/webhooks/app/refunds-disputes) |
| `app.payment.refunded` | `refund` | Deprecated alias of `app.refund.created` | [App events: refunds and disputes](/docs/webhooks/app/refunds-disputes) |
| `app.dispute.flagged` | `dispute` | An early chargeback warning on a one-time purchase | [App events: refunds and disputes](/docs/webhooks/app/refunds-disputes) |
| `app.dispute.created` | `dispute` | A formal dispute is opened on a one-time purchase | [App events: refunds and disputes](/docs/webhooks/app/refunds-disputes) |
| `app.experience.action.payment.pending` | `experience_action_payment` | A fan's charge for a priced action is attempted | [App events: experience actions](/docs/webhooks/app/experience-actions) |
| `app.experience.action.payment.succeeded` | `experience_action_payment` | The charge settles; fulfil on this event only | [App events: experience actions](/docs/webhooks/app/experience-actions) |
| `app.experience.action.payment.failed` | `experience_action_payment` | The charge is declined | [App events: experience actions](/docs/webhooks/app/experience-actions) |
| `app.experience.action.refund.created` | `experience_action_refund` | A settled action purchase is reversed | [App events: experience actions](/docs/webhooks/app/experience-actions) |
| `app.experience.action.dispute.flagged` | `experience_action_dispute` | An early chargeback warning on an action purchase | [App events: experience actions](/docs/webhooks/app/experience-actions) |
| `app.experience.action.dispute.created` | `experience_action_dispute` | A formal dispute on an action purchase | [App events: experience actions](/docs/webhooks/app/experience-actions) |

`app.payment.*` events cover one-time purchases and subscription charges alike, so branch on `billing_reason` to tell them apart. `app.subscription.deactivated` is reserved and never emitted.

## Setup and delivery

App events go to your app's own destinations, never to a creator's. Register them in the **Events** tab or in `webhooks.destinations` of your App Manifest; see [Subscribe to webhooks](/docs/webhooks/subscribing).

| Rule | Behaviour |
| - | - |
| Scope | Every `app.*` event requires `read:self`. Add it on the **Authentication** tab or to [`oauth.scopes`](/docs/app-store/app-manifest/schema#oauth) in your App Manifest. |
| Recipient | Your app's destinations only. The payload concerns your sale: the buyer uuid and the amounts, never a creator's wider activity. |
| Subscription paths | Events tab and App Manifest. The API cannot subscribe to `app.*`. |
| Signing | The per-app signing secret from **View signing secret**. |
| Routing | `app.*` events share endpoints with every other family you subscribe to. Branch on `type` and `data.object`. |

## Event envelope

Every app event arrives in the shared [envelope](/docs/webhooks/index#event-envelope). Here is an `app.payment.succeeded` delivery:

```json theme={null}
{
  "id": "9f2c1e7a4b8d6f30a1c2e3d4b5a6978c0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b",
  "type": "app.payment.succeeded",
  "timestamp": "2026-06-17T13:12:45.123Z",
  "data": { "object": "payment", "...": "resource fields" }
}
```

`id` is a hash of your app, the event's own identifier and the topic, so it is stable across retries. On `app.subscription.*` the hash covers the subscription and the topic rather than the occurrence; see [Repeated subscription state transitions](/docs/webhooks/delivery-and-idempotency#repeated-subscription-state-transitions).

`data.object` is one of `payment`, `subscription`, `refund`, `dispute`, `experience_action_payment`, `experience_action_refund` or `experience_action_dispute`.

## Amounts and currency

Amounts are integers in USD cents, so `999` means \$9.99; [Units and currency](/docs/payments/overview#units-and-currency) covers fees and settlement. `currency` is always `"USD"` on every app payment, refund and experience-action event. Dispute resources are the exception: they carry the processor's `currency`, which can be `null`.

## Money and access are separate events

A subscription's initial charge emits both `app.payment.succeeded` with `billing_reason: "subscription_initial"` and `app.subscription.activated`. Fulfil access from the subscription event and reconcile revenue from the payment event.

<Note>
  `app.refund.created`, `app.payment.refunded` and `app.dispute.*` cover one-time purchases only, identified by a `purchase_reference` with the `appotp_` prefix. Subscription reversals and chargebacks are reconciled through [`GET /apps/{appUuid}/subscription-status`](/docs/payments/app-billing/subscription-status), not these events.
</Note>

## Attribution

`metadata` on every app resource echoes the `client_metadata` captured with the purchase, as an object of string keys and values, and is `{}` when none was set.

`client_reference_id` is captured for one-time item purchases when you append it to the item's checkout link, and it is echoed on the related `app.payment.*` and refund events. It is `null` on subscription charges and when not provided. See [One-time items](/docs/payments/app-billing/one-time-items#attribution).

## Reconciliation

Webhooks can be missed or delayed, so reconcile against the REST endpoints. The app payment endpoints are read-only and require `read:self`. They split into owner-scoped and caller-scoped reads.

| Endpoint | Scope | Returns |
| - | - | - |
| `GET /apps/{appUuid}/payments` | Owner | All buyers' one-time payments for an app you own |
| `GET /apps/{appUuid}/payments/{invoiceNumber}` | Owner | One payment by Fanvue invoice number |
| `GET /apps/{appUuid}/payments/me` | Caller | The authenticated user's own one-time payments for the app |
| `GET /apps/{appUuid}/payments/me/{invoiceNumber}` | Caller | The caller's own payment by invoice number |

`invoiceNumber` matches `data.id` on a payment or `data.payment_id` on a refund. For subscription state use `GET /apps/{appUuid}/subscription-status`; for action purchases use `GET /experiences/{uuid}/action-purchases`. All of these appear under Apps and Experiences in the [API reference](/docs/api-reference/overview).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.