===== Platform Admin Tips ===== {{INLINETOC 3}} ==== Configuring subscriptions ==== **Guide: Product configuration in the subscription system (entitlements & credits)** Using the “Credit & Entitlement” architecture, we configure products in the backend so that they directly control our internal business logic (costs, credits, feature activations). The system supports seamless transitions between different tiers (upgrades and downgrades). === 1. The most important fields in the product === * **''creditPrice'' (The ‘chameleon’ field for credits)**: This field controls credit transactions, but behaves differently depending on the payment method and subscription type: * **Purchase via internal wallet (''paidWithCredits = true''):** The value defines the pure **cost**. The amount is debited from the wallet (for one-off purchases or on a recurring basis for the automatic renewal of internal subscriptions). * **Purchase via Stripe / real money (''paidWithCredits = false''):** This value defines the **credit equivalent** of the real-money payment. The system distinguishes between different types: * //For credit subscriptions (top-up subscriptions):// The value acts purely as a **top-up** and is automatically added to the wallet as ''WALLET_TOP_UP'' . * //For feature subscriptions:// The system effectively carries out a **currency conversion with direct disbursement** . The amount is credited to the wallet and, at the same time, debited again to activate the feature. Furthermore, this value forms the mandatory basis for calculating pro-rata refunds in the event of future tier changes (upgrades or downgrades). * **''billingInterval'' (cycle)**: Optional. Specifies whether this is a subscription (e.g. ''"month"'' or ''"year"''). * **''additionalProperties'' -> ''subscriptionInfo'' (The core feature)**: A JSON object that defines what the ''entitlement'' (internal subscription) exactly unlocks for the user. === 2. Structure of subscriptionInfo (JSON) === The ''subscriptionInfo'' directly controls the permissions (''HostFeature'') of the user. * ''type'': The category bracket (e.g. ''"credit"'', ''"licence"'', ''"visualiser"''). Per user and ''type'' , there is always a maximum of one active entitlement. * ''level'': The configuration level. Higher levels override lower levels of the same type (and vice versa in the case of downgrades). * ''features'': A key-value object for specific rights. The backend processes the values by type: * **Boolean (''true''):** Is adopted 1:1 as a flag (e.g. ''"panorama.model3ds": true'' becomes ''panorama.model3ds = "true"''). * **Number (''Integer''):** The backend combines the key and the number to form a new flag string (e.g. ''"host.licences.visualizer": 3'' becomes ''host.licences.visualizer3 = "true"''). === 3. Configuration examples === == Case A: A standard feature subscription (e.g. Visualizer Level 3) == A typical product for new customers or for changing subscription levels (upgrades and downgrades). * ''creditPrice'': ''50'' (Cost for wallet payments / equivalent value for Stripe payments for currency conversions and subsequent refunds) * ''billingInterval'': ''"month"'' * ''subscriptionInfo'': "subscriptionInfo": { "type": "visualizer", "level": 3, "features": { "host.licences.visualizer": 3, "panorama.model3ds": true } } **What happens?** The backend books the entitlement for type ''"visualizer"'' and sets the HostFeatures ''host.licences.visualizer3 = "true"'' as well as ''panorama.model3ds = "true"'' . Old Visualizer keys from a previous level (e.g. ''visualizer2'') are automatically cleared in the process. == Case B: Similar to the Visualizer subscription (Licence Level 2) == Another level-based subscription with an annual billing cycle. * ''creditPrice'': ''150'' * ''billingInterval'': ''"year"'' * ''subscriptionInfo'': "subscriptionInfo": { "type": "licence", "level": 2, "features": { "host.licences.licence": 2 } } == Case C: The credit top-up subscription (pure Stripe product) == This product is designed to be paid for regularly via Stripe, with credits credited to the user’s wallet in return. * ''creditPrice'': ''100'' (As it is a "credit" type, this serves purely as a top-up value) * ''billingInterval'': ''"month"'' * ''subscriptionInfo'': "subscriptionInfo": { "type": "credit", "features": {} } **What happens?** The user pays real money via Stripe. The webhook recognises the type ''"credit"'' and skips the direct chargeback. The ''creditPrice'' of ''100'' remains as ''WALLET_TOP_UP'' in the user’s wallet. Pro-rata refunds are automatically disabled for this type.