Documentation Index
Fetch the complete documentation index at: https://setup.despia.com/llms.txt
Use this file to discover all available pages before exploring further.
Installation
- Bundle
- CDN
Schemes
Launch a paywall
Opens the RevenueCat native paywall UI configured in your RevenueCat dashboard. The paywall handles product selection, pricing display, and the purchase flow.| Parameter | Required | Description |
|---|---|---|
external_id | Yes | Your user’s ID in RevenueCat. Must match the ID used everywhere else in your app. |
offering | Yes | The RevenueCat offering ID to display. Set to default to use your default offering. |
Direct purchase
Triggers a purchase for a specific product without showing a paywall UI. Use this when you have your own custom purchase UI.| Parameter | Required | Description |
|---|---|---|
external_id | Yes | Your user’s ID in RevenueCat. |
product | Yes | The product ID. iOS uses the plain product ID. Android requires the subscription group prefix: group:productId. |
: is the subscription group name as configured in Google Play Console.
Customer Center
Opens the RevenueCat Customer Center, the native UI that lets users restore purchases, manage their subscription, request refunds (iOS only), and complete feedback surveys. All actions inside the sheet stream back to your web layer throughwindow.onRevenueCatCenter.
| Parameter | Required | Description |
|---|---|---|
external_id | No | Your user’s ID in RevenueCat. If omitted, the Customer Center opens for the currently logged-in RevenueCat user. |
Check entitlements
Queries the native store for all purchases on the current device/account. Returns active subscriptions, expired subscriptions, and one-time purchases. Instant and offline-capable.Purchase callback
The Despia runtime callswindow.onRevenueCatPurchase() immediately when the store confirms a transaction client-side. This is a signal that a transaction occurred, not confirmation that access should be granted.
Do not grant access based on the callback alone if you have a backend. The callback fires before your server has received and processed the RevenueCat webhook. Always wait for your backend to confirm before unlocking features.
getpurchasehistory:// inside the callback to check entitlements directly from the store:
Customer Center callback
The Despia runtime callswindow.onRevenueCatCenter(event) for every action a user takes inside the Customer Center sheet, plus when the sheet itself is dismissed. Set up a single handler and switch on event.event.
Recommended pattern: fully safe restore
When the user runs Restore Purchases from inside the Customer Center, run your existing Despia restore flow on top of the Customer Center’s own restore. Both paths hit the native store, but firing yourgetpurchasehistory:// query plus entitlement check on restoreCompleted guarantees your web app reflects whatever the device actually thinks is true. The Customer Center event tells you the user finished a restore. The Despia call confirms what they restored.
The event payload’s
activeEntitlements array is convenient but not authoritative. Always run getpurchasehistory:// yourself after a state-changing event. The native store is the source of truth, the events are just signals that something might have changed.Events
| Event | Fields | Description |
|---|---|---|
restoreStarted | none | User tapped Restore Purchases. |
restoreCompleted | activeEntitlements, activeSubscriptions, originalAppUserId | Restore succeeded. The arrays reflect post-restore state, but treat them as informational. Re-run your own Despia restore and entitlement check for the fully safe path. |
restoreFailed | errorMessage, errorCode, errorDomain | Restore failed. Use errorCode and errorDomain to branch on specific failure types. |
manageSubscriptionsOpened | none | User opened the native manage-subscriptions sheet. Does not mean they cancelled, only that they navigated to where they could. |
refundRequested | productId | iOS only. User initiated a refund request. Google Play has no equivalent in-app refund flow. |
refundCompleted | productId, status | iOS only. Refund request returned. status is success, userCancelled, or error. success means the request was submitted, not approved. Approval is server-side only. |
feedbackSurveyCompleted | optionId | User completed a feedback survey configured in your RevenueCat dashboard. optionId matches the option identifier set up there. |
managementOptionSelected | option, uri | User selected a management path. option is a string with one of: cancel, changePlans (iOS only), missingPurchase, refundRequest (iOS only), customUrl. For customUrl, the destination URL is in the uri field. |
dismissed | none | User closed the Customer Center sheet. The runtime also auto-refreshes RevenueCat state at this point, so any change made inside the sheet flows through window.onRevenueCatPurchase shortly after. |
All Customer Center events are client-side. They fire while the user is interacting with the sheet. Server-side outcomes such as Apple actually approving a refund, renewals, expirations while the app is closed, and billing failures require RevenueCat webhooks.
Android refund fallback
Google Play does not allow apps to trigger refund requests in-app. The Customer Center on Android has no refund button for this reason, and therefundRequested / refundCompleted events never fire on Android.
To give Android users a path to refunds, configure a custom URL management option in your RevenueCat Customer Center dashboard, then route it client-side using a User-Agent check.
customUrl destinations for the Android refund path:
| Destination | Use when |
|---|---|
mailto:support@yourapp.com?subject=Refund%20request | Default fallback. Works for any refund window. Most users default to email. Lets you handle the refund manually through RevenueCat’s dashboard. |
https://play.google.com/store/account/subscriptions | Only useful within 48 hours of purchase, the window during which Google Play self-service refunds are allowed. |
| Your own support page | If you have a help center or refund form. |
iOS users never hit the
customUrl branch for refunds because the native refund flow is built into the Customer Center. The User-Agent check above is purely to give Android users a path that doesn’t dead-end.REFUND webhook event back to your endpoint so your backend stays in sync.
getpurchasehistory:// response fields
Each item in restoredData has the following fields:
| Field | Type | Description |
|---|---|---|
transactionId | string | Unique ID for this specific transaction |
originalTransactionId | string | ID of the original purchase, links renewals together |
productId | string | Product identifier from App Store Connect or Google Play Console |
type | string | "subscription" or "product" (one-time purchase) |
entitlementId | string | The entitlement this purchase grants, as configured in RevenueCat |
isActive | boolean | Whether this purchase currently grants access |
willRenew | boolean | Whether a subscription will auto-renew |
purchaseDate | string | ISO timestamp of the most recent transaction |
originalPurchaseDate | string | ISO timestamp of the first purchase |
expirationDate | string | null | ISO timestamp when access expires. Null for lifetime purchases. |
store | string | "app_store" or "play_store" |
country | string | User’s country code |
environment | string | "production" or "sandbox" |
externalUserId | string | The external_id set during purchase |
receipt | string | Raw receipt data for server-side validation |
Entitlement check pattern
Set up entitlements in your RevenueCat dashboard first: create an entitlement (e.g.premium), then attach both your iOS and Android products to it. Both platforms will then return the same entitlementId in the response.
Client-side entitlement checks only reflect native iOS and Android purchases. If a user purchased on web,
getpurchasehistory:// will not show that purchase. For apps with web payments, check your backend first and use the native store check as a secondary fallback.Web fallback
NeitherlaunchPaywall nor purchase work in a standard browser. Always detect the Despia runtime and fall back to a RevenueCat Web Purchase Link.
Always append the user’s ID to the Web Purchase Link URL. The user must already exist in your database before you redirect them, RevenueCat includes the
app_user_id in every webhook event, and if your backend cannot find that user the purchase cannot be granted.| Parameter | Description |
|---|---|
?email= | Pre-fills the email field at checkout |
?currency=EUR | Override automatic currency selection |
?package_id= | Pre-select a package and skip to checkout |
?skip_purchase_success=true | Skip the success page and fire the configured redirect immediately |
Webhook handler
Server-side webhooks are the recommended way to track subscription state. They let you revoke access on expiry, handle billing issues, and sync state across platforms in real time.Register the webhook
- Go to RevenueCat Dashboard > Integrations > Webhooks
- Set the URL to your endpoint e.g.
https://yourapp.com/webhooks/revenuecat - Set the Authorization header to a random secret stored in your environment variables
- Select All events and save
Endpoint
Some backends (Supabase Edge Functions, Convex) apply authentication middleware by default that will block incoming RevenueCat requests. Disable the default auth middleware on this endpoint so RevenueCat’s Authorization header reaches your handler.
Webhook event types
| Event | is_active | Notes |
|---|---|---|
INITIAL_PURCHASE | true | First purchase of a product |
RENEWAL | true | Subscription renewed |
UNCANCELLATION | true | User re-enabled a cancelled subscription |
SUBSCRIPTION_EXTENDED | true | Expiry extended |
CANCELLATION | true | Cancelled but active until expires_at |
EXPIRATION | false | Access ended, revoke immediately |
REFUND | false | Refunded, revoke immediately |
BILLING_ISSUE | true | Grace period started |
Database schema
Restore purchases
Required by App Store guidelines. Callgetpurchasehistory:// and re-grant any active entitlements found.
restoreCompleted and run your own Despia restore plus entitlement check rather than trusting the event payload alone. The native store is the source of truth, the events are just triggers.
Resources
NPM Package
despia-native
RevenueCat Dashboard
Configure entitlements, offerings, and paywalls
RevenueCat Webhooks
Event types, fields, and sample payloads