Skip to main content
Fans can pay for an experience in two ways: they buy access to it, or they buy priced actions inside it, such as a spin or a reveal. Every charge is between the fan and the creator. Your app declares what can be bought, triggers the charge and fulfils on the webhook. You need a published experience (see Publish experiences) and a webhook endpoint that receives App events. For priced actions there are two charge paths:

Who gets paid

The creator is the seller on every experience invoice, at the standard Fanvue fee. Your app isn’t a party to the charge and receives no share. Every price is in USD cents, from 300 to 50000. What each access mode charges, and when it renews: Fans buy PAID access in Fanvue’s native checkout from the detail page, a chat card or the experience dialog. The purchase.new webhook carries experienceUuid and experienceAppUuid, and so does every row of GET /insights/earnings for the experience. Recurring access mints a monthly price, and subscriptions renew automatically at the original price. Renewal pauses while the app is suspended, and stops when:
  • the experience is unpublished
  • the experience is no longer PAID
  • the experience is no longer recurring
  • the app is uninstalled
A failed renewal enters dunning with no experience-specific grace. The creator.experience_subscription.activated and creator.experience_subscription.deactivated webhooks report the lifecycle; see Creator events: experience subscriptions. SUBSCRIPTION access produces no charge and no webhook of its own.

Priced actions

A priced action is something a fan buys inside your experience, such as a spin or a reveal. Each experience carries a catalogue of up to 10. The creator prices them, in the confirmation dialog or through a price-request from your creator surface, unless your app prices them in a direct publish. GET /experiences/{experienceUuid}/actions (read:experience) returns the live catalogue, re-priced on every read.
title is the creator-facing label shown in the payment dialog. status is always active, because a withdrawn action is omitted rather than returned as disabled. GET /apps/{appUuid}/experience-action-definitions (read:experience) returns the actions your app has declared, without any amount. It answers 404 when the creator hasn’t installed your app.

Charge path 1: the purchase bridge

Your fan surface posts a purchase request and Fanvue opens its native payment dialog. The request never carries an amount, because the price comes from the catalogue.
Two more fan bridges support the wallet:
  • fanvue:experience:topup-request with { amountMinorUnits, clientReferenceId? } opens the top-up dialog and answers topup-result with { status, clientReferenceId?, invoiceNumber? }.
  • fanvue:experience:consent-request with { clientReferenceId? } asks for spend consent and answers consent-result with { status: "granted" | "declined" | "failed" }. A fan who has already consented gets granted with no dialog.
Fan surface and creator surface messages lists every message.

Charge path 2: wallet charge from your server

POST /experiences/{experienceUuid}/action-purchases (write:experience) charges one action to the fan’s wallet with no dialog. The Idempotency-Key header is required.
A 201 returns the purchase plus walletBalance, the fan’s remaining balance in USD cents. Purchase references are prefixed expact_. Idempotency keys are scoped to your app, the fan and the experience, and remembered for 24 hours. Reusing a key replays the first charge once it has settled. The charge needs a live spend consent for this app and experience. The fan grants it by topping up inside the experience or by answering consent-request, and can revoke it.

Fulfil on the webhook

Fulfil only on app.experience.action.payment.succeeded, keyed on purchase_reference, so a redelivery grants nothing twice. The bridge result is never proof of payment. For what to do on each status, including when to revoke a grant, see the fulfilment rule. Six events cover the lifecycle, under the read:self scope: app.experience.action.payment.pending, app.experience.action.payment.succeeded, app.experience.action.payment.failed, app.experience.action.refund.created, app.experience.action.dispute.flagged and app.experience.action.dispute.created. App events: experience actions has the payloads.

Reconcile

GET /experiences/{experienceUuid}/action-purchases lists every attempt, newest first, with keyset paging through nextCursor (limit default 50, max 100). GET /experiences/{experienceUuid}/action-purchases/{purchaseReference} reads one.

Refunds

Refunds have no API. Fanvue re-derives access from the payment ledger on every launch, so a refunded unlock loses access on the fan’s next launch. A refunded action reports refunded on the webhook and on the purchase reads.

See also