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

# Checkout Payment Events

> Reference for the payment.pending, payment.succeeded, and payment.failed webhooks that fire on Fanvue checkout-link payments, with payload fields.

Three events share the `payment` resource. They are delivered in the [Standard-Webhooks envelope](/docs/checkout/overview#event-envelope); the fields below describe the `data` object.

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

`checkout_link.payment.succeeded` covers one-off purchases, initial subscription payments, and renewals. Branch on `billing_reason` to tell them apart.

## Payment resource

| Field                 | Type            | Description                                                                                             |
| --------------------- | --------------- | ------------------------------------------------------------------------------------------------------- |
| `object`              | string          | Always `"payment"`                                                                                      |
| `id`                  | string          | Fanvue invoice number (e.g. `FV-12345`)                                                                 |
| `status`              | string          | `pending` \| `succeeded` \| `failed`                                                                    |
| `billing_reason`      | string          | `one_time` \| `subscription_initial` \| `subscription_renewal`                                          |
| `reason`              | string \| null  | Sanitised failure reason on `payment.failed`; `null` otherwise. See [Failure reasons](#failure-reasons) |
| `gross`               | integer         | Gross amount in minor units                                                                             |
| `net`                 | integer \| null | Creator net after fees, in minor units                                                                  |
| `fees`                | object          | `{ fanvue_fee, transaction_fee }` in minor units (each may be `null`)                                   |
| `currency`            | string \| null  | ISO 4217 currency code                                                                                  |
| `paid_in_full`        | boolean         | Whether the full amount has been collected (see [BNPL installments](#bnpl-installments))                |
| `installment`         | object \| null  | `{ number, of }` for a BNPL financed sale; `null` for a normal payment                                  |
| `subscription`        | object \| null  | `{ uuid }` when the payment is tied to a subscription                                                   |
| `client_reference_id` | string \| null  | Your passthrough reference (see [Attribution](/docs/checkout/attribution))                                   |
| `transaction_id`      | string \| null  | Processor transaction id                                                                                |
| `created_at`          | string \| null  | ISO 8601 creation time                                                                                  |
| `paid_at`             | string \| null  | ISO 8601 time the payment was paid (`null` until paid)                                                  |
| `checkout_link`       | object          | `{ uuid, name, product_uuid, product_price_uuid }`                                                      |
| `purchaser`           | object          | `{ uuid, email }` of the buyer (`email` may be `null`)                                                  |
| `creator`             | object          | `{ uuid }` of the creator                                                                               |
| `metadata`            | object          | Your passthrough metadata map                                                                           |

## Failure reasons

`checkout_link.payment.failed` carries a sanitised `reason`. Values are deliberately coarse: Fanvue's risk screening is never disclosed, so declines it drives surface under neutral values.

| `reason`              | What happened                                                   | What to do                                                                                    |
| --------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `insufficient_funds`  | The buyer's account can't cover the charge                      | Soft decline; worth the buyer retrying later or with another method                           |
| `expired_card`        | The card has expired                                            | The buyer needs a different or updated card                                                   |
| `bank_decline`        | The issuer declined without a more specific reason              | Another attempt or method may succeed; persistent declines mean the buyer contacts their bank |
| `invalid_details`     | Card or billing details were invalid or malformed               | The buyer re-enters their details                                                             |
| `verification_failed` | A verification check (CVV, AVS, 3DS) failed or wasn't completed | The buyer retries and completes verification                                                  |
| `limit_exceeded`      | An issuer limit was hit: amount, daily spend, or attempts       | Retry later, or with a smaller amount or different method                                     |
| `other`               | No specific category, including technical failures              | Retry later; a different method if it persists                                                |

Two rules:

1. **You don't retry charges yourself.** Checkout is buyer-present: a failed one-time payment ends there unless the buyer tries again, and failed renewals enter Fanvue's own retry schedule (dunning). Don't treat the first failed renewal as churn.
2. **Use `reason` for ops and analytics**: spotting a decline spike, deciding when to re-engage a buyer, reconciling failed revenue.

## BNPL installments

When a fan finances a purchase with Buy Now, Pay Later (BNPL), Fanvue is paid upfront, so the sale still arrives as a single `checkout_link.payment.succeeded`. The only difference is that it is marked as a financed sale:

* `paid_in_full` is `false`, and
* `installment` is `{ "number": 1, "of": N }` (the first of `N` installments).

The fan's later repayments (installments `2..N`) are **financing movement**, not new Fanvue sales. Fanvue has already been paid. Those repayments arrive as [`checkout_link.installment.paid` / `.failed`](/docs/checkout/installments) events, **not** as further `payment.succeeded` events, and the plan finishing emits [`checkout_link.plan.completed`](/docs/checkout/installments).

For a normal (non-financed) payment, `installment` is `null` and `paid_in_full` is `true` once collected.

## Failure reasons

`checkout_link.payment.failed` carries a sanitised `reason`. Values are deliberately coarse: Fanvue's risk screening is never disclosed, and declines it drives surface under neutral values.

| `reason`              | What happened                                                   | What to do                                                                                          |
| --------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `insufficient_funds`  | The buyer's account can't cover the charge                      | Soft decline: the buyer can retry later or use another method                                       |
| `expired_card`        | The card has expired                                            | The buyer needs an updated or different card                                                        |
| `bank_decline`        | The issuer declined without a more specific reason              | Another attempt or method may succeed; persistent declines mean the buyer should contact their bank |
| `invalid_details`     | Card or billing details were invalid or malformed               | The buyer re-enters their details                                                                   |
| `verification_failed` | A verification check (CVV, AVS, 3DS) failed or wasn't completed | The buyer retries and completes verification                                                        |
| `limit_exceeded`      | An issuer limit was hit: amount, daily spend, or attempts       | Soft decline: retry later, or with a smaller amount or different method                             |
| `other`               | No specific category, including technical failures              | Retry later; a different method if it persists                                                      |

Two rules:

* **You don't retry charges yourself.** Checkout is buyer-present: a failed one-time payment ends unless the buyer tries again, and failed **renewals** enter Fanvue's own retry schedule, so don't treat the first `payment.failed` on a renewal as churn.
* Use `reason` for ops and analytics: spotting a decline spike, deciding when to re-engage a buyer, and reconciling failed revenue.

## Examples

### `checkout_link.payment.succeeded`

```json theme={null}
{
  "id": "f1a2b3c4-1111-4a2b-9c3d-aaaaaaaaaaaa",
  "type": "checkout_link.payment.succeeded",
  "timestamp": "2026-06-09T08:39:33.139Z",
  "data": {
    "object": "payment",
    "id": "FV-12345",
    "status": "succeeded",
    "billing_reason": "subscription_initial",
    "gross": 9999,
    "net": 8000,
    "fees": { "fanvue_fee": 1500, "transaction_fee": 499 },
    "currency": "USD",
    "paid_in_full": true,
    "installment": null,
    "subscription": { "uuid": "sub-uuid" },
    "client_reference_id": "your-crm-id-123",
    "transaction_id": "txn_abc",
    "created_at": "2026-06-09T08:39:30.000Z",
    "paid_at": "2026-06-09T08:39:33.000Z",
    "checkout_link": {
      "uuid": "ck-uuid",
      "name": "VIP Monthly",
      "product_uuid": "prod-uuid",
      "product_price_uuid": "pp-uuid"
    },
    "purchaser": { "uuid": "fan-uuid", "email": "fan@example.com" },
    "creator": { "uuid": "creator-uuid" },
    "metadata": { "affiliate_id": "aff_123", "campaign": "spring" }
  }
}
```

### `checkout_link.payment.succeeded` (BNPL financed sale)

The initial financed sale carries `paid_in_full: false` and `installment: { number: 1, of: N }`. `gross` is the full sale amount; `currency` is what the fan is charged (the processing currency). Repayments `2..N` then arrive as [installment events](/docs/checkout/installments).

```json theme={null}
{
  "id": "f1a2b3c4-9999-4a2b-9c3d-aaaaaaaaaaaa",
  "type": "checkout_link.payment.succeeded",
  "timestamp": "2026-06-09T08:39:33.139Z",
  "data": {
    "object": "payment",
    "id": "FV-12350",
    "status": "succeeded",
    "billing_reason": "one_time",
    "gross": 30000,
    "net": 24000,
    "fees": { "fanvue_fee": 4500, "transaction_fee": 1500 },
    "currency": "EUR",
    "paid_in_full": false,
    "installment": { "number": 1, "of": 3 },
    "subscription": null,
    "client_reference_id": "your-crm-id-123",
    "transaction_id": "txn_split_1",
    "created_at": "2026-06-09T08:39:30.000Z",
    "paid_at": "2026-06-09T08:39:33.000Z",
    "checkout_link": {
      "uuid": "ck-uuid",
      "name": "Premium Bundle",
      "product_uuid": "prod-uuid",
      "product_price_uuid": "pp-uuid"
    },
    "purchaser": { "uuid": "fan-uuid", "email": "fan@example.com" },
    "creator": { "uuid": "creator-uuid" },
    "metadata": { "affiliate_id": "aff_123", "campaign": "spring" }
  }
}
```

### `checkout_link.payment.pending`

```json theme={null}
{
  "id": "f1a2b3c4-2222-4a2b-9c3d-aaaaaaaaaaaa",
  "type": "checkout_link.payment.pending",
  "timestamp": "2026-06-09T08:39:33.139Z",
  "data": {
    "object": "payment",
    "id": "FV-12346",
    "status": "pending",
    "billing_reason": "one_time",
    "gross": 1499,
    "net": 1200,
    "fees": { "fanvue_fee": 224, "transaction_fee": 75 },
    "currency": "USD",
    "paid_in_full": false,
    "installment": null,
    "subscription": null,
    "client_reference_id": "your-crm-id-123",
    "transaction_id": "txn_def",
    "created_at": "2026-06-09T08:39:30.000Z",
    "paid_at": null,
    "checkout_link": {
      "uuid": "ck-uuid",
      "name": "Summer Bundle",
      "product_uuid": "prod-uuid",
      "product_price_uuid": "pp-uuid"
    },
    "purchaser": { "uuid": "fan-uuid", "email": "fan@example.com" },
    "creator": { "uuid": "creator-uuid" },
    "metadata": { "affiliate_id": "aff_123", "campaign": "spring" }
  }
}
```

### `checkout_link.payment.failed`

```json theme={null}
{
  "id": "f1a2b3c4-3333-4a2b-9c3d-aaaaaaaaaaaa",
  "type": "checkout_link.payment.failed",
  "timestamp": "2026-06-09T08:39:33.139Z",
  "data": {
    "object": "payment",
    "id": "FV-12347",
    "status": "failed",
    "billing_reason": "subscription_renewal",
    "reason": "insufficient_funds",
    "gross": 9999,
    "net": 8000,
    "fees": { "fanvue_fee": 1500, "transaction_fee": 499 },
    "currency": "USD",
    "paid_in_full": false,
    "installment": null,
    "subscription": { "uuid": "sub-uuid" },
    "client_reference_id": "your-crm-id-123",
    "transaction_id": "txn_ghi",
    "created_at": "2026-06-09T08:39:30.000Z",
    "paid_at": null,
    "checkout_link": {
      "uuid": "ck-uuid",
      "name": "VIP Monthly",
      "product_uuid": "prod-uuid",
      "product_price_uuid": "pp-uuid"
    },
    "purchaser": { "uuid": "fan-uuid", "email": "fan@example.com" },
    "creator": { "uuid": "creator-uuid" },
    "metadata": { "affiliate_id": "aff_123", "campaign": "spring" }
  }
}
```
