> ## 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 payment events

> Payload reference for app.payment.pending, succeeded and failed on your app's own sales, with billing reasons, failure reasons and decline type.

Three events share the `payment` resource and describe every charge your app bills a creator for, one-time or recurring, against your [pricing plans](/docs/payments/app-billing/pricing-plans).

| Event (`type`) | Fires when |
| - | - |
| `app.payment.pending` | A charge is created and awaiting confirmation |
| `app.payment.succeeded` | A charge succeeds |
| `app.payment.failed` | A charge fails |

Every event requires `read:self`. Each arrives in the [envelope](/docs/webhooks/index#event-envelope), and the tables below describe `data`. `app.payment.*` events cover one-time purchases and subscription charges alike, so branch on `billing_reason` to tell them apart. A subscription's initial charge emits both `app.payment.succeeded` with `billing_reason: "subscription_initial"` and [`app.subscription.activated`](/docs/webhooks/app/subscriptions).

## Payment resource

`data.object` is `"payment"` for all three events. Amounts are integers in USD cents.

| Field | Type | Description |
| - | - | - |
| `object` | string | Always `"payment"` |
| `id` | string | Fanvue invoice number for the payment |
| `status` | string | `pending` \| `succeeded` \| `failed` |
| `billing_reason` | string | `one_time` \| `subscription_initial` \| `subscription_renewal` \| `subscription_update` |
| `gross` | integer | Gross amount in USD minor units |
| `currency` | string | Always `"USD"` |
| `reason` | string \| null | Failure reason on `failed`: `insufficient_funds` \| `expired_card` \| `bank_decline` \| `invalid_details` \| `verification_failed` \| `limit_exceeded` \| `other`. `null` on `pending` and `succeeded` |
| `decline_type` | string \| null | `soft` \| `hard` on `failed` when known; `soft` declines are retryable. `null` otherwise |
| `purchase_reference` | string | `appotp_` reference for a one-time purchase, `appupg_` reference for an upgrade proration, otherwise the subscription's billing reference |
| `client_reference_id` | string \| null | Your attribution reference for one-time purchases, from the item checkout link. `null` on subscription charges and when not provided. See [One-time items](/docs/payments/app-billing/one-time-items#attribution) |
| `metadata` | object | `client_metadata` captured with the purchase, string keys and values. `{}` when none was set |
| `created_at` | string \| null | ISO 8601 creation time |
| `paid_at` | string \| null | ISO 8601 time the payment was paid. `null` until paid |
| `item` | object | `{ uuid }` of the purchased pricing plan. `uuid` is `null` when unknown |
| `app` | object | `{ uuid }` of your app |
| `buyer` | object | `{ uuid }` of the buyer |

Risk-screening declines report `reason: "other"`, and the raw processor message is never forwarded.

### Billing reasons

| `billing_reason` | Charge |
| - | - |
| `one_time` | A one-time item purchase. `purchase_reference` starts with `appotp_` |
| `subscription_initial` | The first charge of a subscription |
| `subscription_renewal` | A recurring renewal charge |
| `subscription_update` | A mid-cycle upgrade proration. `purchase_reference` starts with `appupg_` |

## Examples

### `app.payment.succeeded` (subscription initial charge)

```json theme={null}
{
  "id": "9f2c1e7a4b8d6f30a1c2e3d4b5a6978c0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b",
  "type": "app.payment.succeeded",
  "timestamp": "2026-06-17T13:12:45.123Z",
  "data": {
    "object": "payment",
    "id": "INV-2026-000123",
    "status": "succeeded",
    "billing_reason": "subscription_initial",
    "gross": 999,
    "currency": "USD",
    "reason": null,
    "decline_type": null,
    "purchase_reference": "sub_3f9a2b71-1c4e-4f8a-9d2b-7c6e5a4b3d21",
    "client_reference_id": null,
    "metadata": {},
    "created_at": "2026-06-17T13:12:40.000Z",
    "paid_at": "2026-06-17T13:12:44.880Z",
    "item": { "uuid": "b2d7c9f0-4a13-4e6b-8f25-1a9c3e7d5b80" },
    "app": { "uuid": "a1c3e5f7-9b2d-4c6e-8a0f-2d4b6c8e0a13" },
    "buyer": { "uuid": "c4e6a8b0-2d4f-6a81-0c2e-4b6d8f0a2c46" }
  }
}
```

A one-time purchase carries `"billing_reason": "one_time"` and an `appotp_` purchase reference, and a renewal carries `"billing_reason": "subscription_renewal"`.

### `app.payment.pending`

```json theme={null}
{
  "id": "1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6",
  "type": "app.payment.pending",
  "timestamp": "2026-06-17T13:12:40.500Z",
  "data": {
    "object": "payment",
    "id": "INV-2026-000124",
    "status": "pending",
    "billing_reason": "one_time",
    "gross": 999,
    "currency": "USD",
    "reason": null,
    "decline_type": null,
    "purchase_reference": "appotp_3f9a2b71-1c4e-4f8a-9d2b-7c6e5a4b3d21",
    "client_reference_id": "campaign-42",
    "metadata": { "affiliate_id": "aff_8812" },
    "created_at": "2026-06-17T13:12:40.000Z",
    "paid_at": null,
    "item": { "uuid": "b2d7c9f0-4a13-4e6b-8f25-1a9c3e7d5b80" },
    "app": { "uuid": "a1c3e5f7-9b2d-4c6e-8a0f-2d4b6c8e0a13" },
    "buyer": { "uuid": "c4e6a8b0-2d4f-6a81-0c2e-4b6d8f0a2c46" }
  }
}
```

### `app.payment.failed`

```json theme={null}
{
  "id": "2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7",
  "type": "app.payment.failed",
  "timestamp": "2026-07-17T13:12:45.000Z",
  "data": {
    "object": "payment",
    "id": "INV-2026-000987",
    "status": "failed",
    "billing_reason": "subscription_renewal",
    "gross": 999,
    "currency": "USD",
    "reason": "bank_decline",
    "decline_type": "soft",
    "purchase_reference": "sub_3f9a2b71-1c4e-4f8a-9d2b-7c6e5a4b3d21",
    "client_reference_id": null,
    "metadata": {},
    "created_at": "2026-07-17T13:12:40.000Z",
    "paid_at": null,
    "item": { "uuid": "b2d7c9f0-4a13-4e6b-8f25-1a9c3e7d5b80" },
    "app": { "uuid": "a1c3e5f7-9b2d-4c6e-8a0f-2d4b6c8e0a13" },
    "buyer": { "uuid": "c4e6a8b0-2d4f-6a81-0c2e-4b6d8f0a2c46" }
  }
}
```

## Reconciling

`data.id` matches the `invoiceNumber` path parameter on `GET /apps/{appUuid}/payments/{invoiceNumber}`. The event `id` hashes your app, the invoice number and the topic, so a re-emitted charge carries the same id and deduplicates on it. See [Reconciliation](/docs/webhooks/app/overview#reconciliation).


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