Skip to main content
Fanvue sends webhooks for your app’s own sales so you can fulfil access and reconcile money: one-time item purchases and subscriptions, their payments, refunds, and disputes. They are scoped to your app’s own sales, so the payload only ever concerns a purchase of your app (the buyer uuid and the amounts), never a creator’s wider platform activity.

Setup and delivery

App webhooks are configured like every other Fanvue webhook: in the Developer Area Events tab, add an endpoint and select the app.* events you want, then enable the required scope. See the Webhooks Overview and legacy setup walkthrough for the full setup, signing secret, and local testing flow.
  • Scope: every app.* event requires the read:self scope, the payload only concerns your app’s own sale (the buyer uuid and amounts). Enable it in the Authentication tab.
  • One endpoint, many events: app.* events arrive on the same endpoints as the platform events (follow.new, purchase.new, …) and checkout events (checkout_link.*) you have subscribed to. Branch on the event type (and data.object) to route them.

Amounts and currency

Monetary amounts are integers in the currency’s minor units (for USD, cents, so 999 means $9.99). Each resource carries its own currency (ISO 4217), which may be null when not yet known.

Event envelope

Every app webhook is delivered as an HTTP POST with a Standard-Webhooks-style envelope:
  • id: unique event id, stable across delivery retries (use it to dedupe). On app.subscription.* the id covers the state transition rather than the occurrence, so pair it with timestamp if the same transition can repeat within a billing period, see Delivery, Retries and Idempotency.
  • type: the event topic (see Available events).
  • timestamp: ISO 8601 time the event was emitted.
  • data: the resource object. data.object is "payment", "subscription", "refund", or "dispute".
Fields inside data are snake_case.

Available events

All app.* events require the read:self scope. Each group below links to a reference page with full field definitions and example payloads.

Payments (reference)

  • app.payment.pending: a charge is created and awaiting confirmation
  • app.payment.succeeded: a charge succeeds
  • app.payment.failed: a charge fails
app.payment.* events cover both one-time purchases and subscription charges; branch on billing_reason to tell them apart.

Subscriptions (reference)

  • app.subscription.activated: a subscription becomes active
  • app.subscription.cancel_at_period_end_changed: auto-renew is turned off; access continues until period end

Refunds and disputes (reference)

  • app.refund.created: a one-time purchase is refunded, charged back, or cancelled
  • app.payment.refunded: deprecated alias of app.refund.created
  • app.dispute.flagged: an early chargeback warning, before a formal dispute
  • app.dispute.created: a formal dispute (chargeback) is opened

Money and access are separate events

The money and the access state arrive as different events: a subscription’s initial charge emits both app.payment.succeeded (with billing_reason: subscription_initial) and app.subscription.activated. Fulfil access off the subscription event and reconcile revenue off the payment event.
Refund and dispute events (app.refund.created, app.payment.refunded, app.dispute.*) cover one-time purchases only, identified by a purchase_reference with the appotp_ prefix. Subscription reversals and chargebacks are reconciled through the App Subscriptions endpoints, not these webhooks.
app.subscription.deactivated is reserved for when a subscription’s access actually ends, but is not emitted yet. Read live subscription state with the App Subscriptions endpoints in the meantime.
metadata appears on every app resource but is currently always empty. client_reference_id is captured for one-time item purchases when you append it to the item’s checkout link, and echoed on the related app.payment.* and refund events; it is null on subscription charges and whenever it wasn’t provided. See One-time Items.

Verifying signatures

App webhooks are signed exactly like the rest of Fanvue’s webhooks, with an X-Fanvue-Signature header (t=<timestamp>,v0=<hmac-sha256-hex>). Verify it against the raw request body before parsing JSON. The header breakdown, the verification flow, and complete Node and Python samples live in Verify Webhook Signatures.

Reconciliation

Webhooks can be missed or delayed, so reconcile against the REST endpoints. The app one-time payments endpoints are read-only, require the read:self scope, and split into owner-scoped (all buyers of an app you own) and caller-scoped (/me, the authenticated user’s own payments): The invoiceNumber path parameter matches data.id (for a payment) or data.payment_id (for the original payment behind a refund). For subscription state, use the App Subscriptions endpoints.
These payment endpoints are not yet part of the generated API Reference; they are documented here until they appear in the OpenAPI spec.