Setup and delivery
App webhooks are configured like every other Fanvue webhook: in the Developer Area Events tab, add an endpoint and select theapp.* 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 theread:selfscope, 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 eventtype(anddata.object) to route them.
Amounts and currency
Monetary amounts are integers in the currency’s minor units (for USD, cents, so999 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 HTTPPOST with a Standard-Webhooks-style envelope:
id: unique event id, stable across delivery retries (use it to dedupe). Onapp.subscription.*the id covers the state transition rather than the occurrence, so pair it withtimestampif 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.objectis"payment","subscription","refund", or"dispute".
data are snake_case.
Available events
Allapp.* 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 confirmationapp.payment.succeeded: a charge succeedsapp.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 activeapp.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 cancelledapp.payment.refunded: deprecated alias ofapp.refund.createdapp.dispute.flagged: an early chargeback warning, before a formal disputeapp.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 bothapp.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 anX-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 theread: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.