Skip to main content
Wildo.ai Coming soon

Billing and subscriptions

Define what your application sells

Describe plans, add-ons and one-time products alongside the features and limits they grant. Wildo turns those definitions into its billing catalogue, so the offer and the application behavior have a shared starting point.

One professional product grants reports and a list allowance, with monthly and yearly billing options.

Define what your application sells

Describe plans, add-ons and one-time products alongside the features and limits they grant. Wildo turns those definitions into its billing catalogue, so the offer and the application behavior have a shared starting point.

Example — A professional plan with a clear allowance

A professional plan includes advanced reports and a larger list allowance. Its monthly and yearly prices belong to that same product.

For engineers

This complete shared-module example defines a monthly organization plan and the feature it grants. It uses the same SharedSaaSModule.productDefinitions registration as Wonder Todos. Merge these contributions into your existing shared engine module; do not replace its other features, roles or products. The example identifiers and offer are application-owned.

import {
  defineFeature, ProductType, ResourcePrimaryScope,
  type ProductDefinition, type SharedSaaSModule,
} from '@wildo-ai/saas-models';
import { BillingInterval, PricingModel } from '@wildo-ai/external-connectors-models';
import { AvailableCurrency } from '@wildo-ai/zod-decorators';

export enum CommercialFeature { REPORTS = 'advanced-reports' }

export const professional: ProductDefinition = {
  key: 'professional',
  type: ProductType.PLAN,
  targetScopes: [ResourcePrimaryScope.ORGANIZATIONS],
  grantedFeatures: [CommercialFeature.REPORTS],
  planTier: 'professional',
  planTierOrder: 1,
  prices: [{
    model: PricingModel.FLAT,
    unitPrice: { amount: 2900n, decimals: 2, currency: AvailableCurrency.USD },
    interval: BillingInterval.MONTH,
    intervalCount: 1,
    isDefault: true,
  }],
};

const engineModule: SharedSaaSModule = {
  moduleId: 'engine',
  kind: 'engine',
  customFeatureDefinitions: [
    defineFeature(CommercialFeature.REPORTS, { scope: ResourcePrimaryScope.ORGANIZATIONS }),
  ],
  productDefinitions: [professional],
};
export default engineModule;

2900n with two decimals means USD 29, not USD 2,900 or USD 0.29. A yearly alternative belongs in the same product’s prices array with BillingInterval.YEAR; it does not need another product or another grant. Keep the product key stable: subscription items and provider mappings use it. Author the offer’s customer-facing labels in the application’s billing labels/specifications.

The module must participate in the application’s assembled shared modules. A declaration in an unimported file does nothing. See billing setup for capability, provider and environment prerequisites.

Check the synchronized offer before selling it

Catalogue synchronization materializes separate Product and Price records and establishes provider mappings. A complete syncProductCatalog() pass reports synchronization errors; on-demand synchronization also supports checkout. A compiled declaration alone is not proof that the provider accepted the price.

What to inspectExpected result
Local productThe stable key, organization scope and report grant match the declaration
Local priceIt belongs to that product and represents USD 29 per month
Provider mappingProduct and price have usable provider identities after synchronization
Customer purchaseSigned provider events establish subscription state; feature synchronization derives the grant

The grant feeds effective entitlements. Protect the report operation with that feature requirement; displaying a plan name does not authorize a report. Follow feature grants for the consuming check.

Retire an offer without rewriting history

A complete sync retires locally stored products absent from the authored catalogue and disables their local prices. It retains the records and reports live subscribers; it does not migrate those subscribers or archive their provider prices. Existing renewal history remains resolvable while new acquisition rejects the retired offer. Provider retirement and customer migration remain deliberate operational decisions.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.