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

# One-time items

> Sell credit packs and other one-time items from your Fanvue app through a checkout URL, attribute each sale, and fulfil it from the webhook.

One-time items are consumables you sell alongside your app, such as credit packs, boosts and top-ups. By the end of this page you'll have an item on sale behind a button in your app and a handler that credits the buyer when payment succeeds. You need an app you'll list on the App Store; [Bill creators through the App Store](/docs/payments/app-billing/overview) shows how billing fits together.

Items are independent of your pricing plans. Buying one changes no installation or subscription, and a creator can buy the same item any number of times. Prices are integers in USD minor units (cents).

## Create an item

In the Developer Area, open your app, go to **Store listing**, then **Pricing**, and click **Add item** under **One-time items**.

| Field | Constraints |
| - | - |
| Item name | Up to 20 characters, for example "500 credits" |
| Description | Up to 500 characters |
| Price | \$3.99 to \$500.00 |

An app holds at most 10 one-time items that are not withdrawn, separate from the 5-plan limit. You receive 80% of each sale, the same [revenue split](/docs/payments/app-billing/overview) as [pricing plans](/docs/payments/app-billing/pricing-plans).

## Selling an item

Items sell through their Fanvue-hosted checkout URL only. Your app decides when to offer one, typically with a "Buy more credits" button pointing at the item's `checkoutUrl`:

```text theme={null}
https://www.fanvue.com/checkout/app_<id>
```

Copy it from the item's row on the **Pricing** tab, or read it as `checkoutUrl` on the item in `GET /apps/{appUuid}/subscription-status`, and put it behind your purchase button. The URL is `null` while the item is pending setup or withdrawn.

Item checkout accepts buyers who are signed in to Fanvue. Because items are independent of plans, whether one works as a first purchase or an in-app top-up depends on how your app gates its features.

Items can't be deeplinked. The `?plan=` parameter on your listing targets subscription plans and treats an item UUID as invalid.

## Attribution

To tie a purchase back to your own records, append `client_reference_id` and `metadata[<key>]` query parameters to the checkout URL:

```text theme={null}
https://www.fanvue.com/checkout/app_<id>?client_reference_id=your-order-123&metadata[campaign]=spring
```

Both are echoed on the resulting `app.payment.*` and `app.refund.created` events as `data.client_reference_id` and `data.metadata`. The limits match [checkout link attribution](/docs/checkout/attribution): 200 characters for `client_reference_id`, and up to 10 `metadata` keys of 40 characters with values of 200 characters. Both are passthrough only. Never put secrets in them, because every receiver of the event sees them.

## Fulfilment

Fulfil off [`app.payment.succeeded`](/docs/webhooks/app/payments):

1. **Identify the purchase.** `billing_reason` is `one_time` and `purchase_reference` starts with `appotp_`. `item.uuid` names the item bought and `buyer.uuid` the creator who bought it.
2. **Dedupe before crediting.** The event `id` is stable across delivery retries, so record it and skip a repeat.
3. **Credit the buyer**, then reconcile revenue against the payment's invoice number in `data.id`.

Don't fulfil on `app.payment.pending`. A pending payment can still fail, and crediting it leaves the buyer with goods Fanvue never charged for.

## Refunds and disputes

[`app.refund.created`](/docs/webhooks/app/refunds-disputes) fires when a payment is reversed, and you branch on its `reason`. `app.dispute.flagged` and `app.dispute.created` warn you of chargebacks. Claw back credited balances keyed on `payment_id`, the invoice number of the original payment.

## Reconciling

You can re-read one-time payments at any time with the app payments endpoints.

| Endpoint | Returns |
| - | - |
| `GET /apps/{appUuid}/payments` | Every buyer's payments for an app you own |
| `GET /apps/{appUuid}/payments/{invoiceNumber}` | One payment by Fanvue invoice number |
| `GET /apps/{appUuid}/payments/me` | The authenticated user's own payments for the app |
| `GET /apps/{appUuid}/payments/me/{invoiceNumber}` | The caller's own payment by invoice number |

The invoice number on each payment matches `data.id` on the `app.payment.*` event.


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