
Turn completed work into billable usage
Metering connects a quantity of completed work to the customer’s billing account. A declared operation can record a fixed amount or read a measured quantity from its result.
Wildo stores that usage before reporting it to the provider. Your application chooses what counts as a billable unit, and the product’s subscription and provider meter determine how that unit is charged.
Example — Bill for pages actually rendered
A document operation returns a page count. Its metering declaration reads that result, so a three-page output records three units instead of charging for the number of pages originally requested.
For engineers
Application example: charge for pages actually rendered. This complete illustrative product follows the engine’s METERED contract and the same per-unit monthly price structure as Wonder Todos’ API-call product. The key and price below are example product choices, not an existing application offer:
import {
ProductType, ResourcePrimaryScope, UsageAggregationType,
type ProductDefinition,
} from '@wildo-ai/saas-models';
import { PricingModel, BillingInterval } from '@wildo-ai/external-connectors-models';
import { AvailableCurrency } from '@wildo-ai/zod-decorators';
export const renderedPagesProduct: ProductDefinition = {
key: 'rendered_pages',
type: ProductType.METERED,
targetScopes: [ResourcePrimaryScope.ORGANIZATIONS],
prices: [{
model: PricingModel.PER_UNIT,
unitPrice: { amount: 1n, decimals: 2, currency: AvailableCurrency.USD },
interval: BillingInterval.MONTH,
intervalCount: 1,
usageAggregation: UsageAggregationType.SUM,
isDefault: true,
}],
};
Add this product to the catalogue contributed by the owning shared module’s productDefinitions. Here 1n with two decimals means USD 0.01 per page. Billing/provider setup and catalogue synchronization must make the metered product available, and the organization must have an active or trialling subscription containing it. The product key is also the meter-event name used when reporting usage.
Connect the operation’s completed result
This complete illustrative operation entry belongs under the report resource’s registered custom render operation. The application still supplies its renderer implementation; the example defines its usage contract and response shape:
import { z } from 'zod';
import {
CORE_ORG_ROLES, CoreResourceOperation,
ResourceOperationRiskLevel, ResourceOperationVariantType,
type OperationConfig_ForKey,
} from '@wildo-ai/saas-models';
export const renderReportOperation: OperationConfig_ForKey<string> = {
variants: [{
variantType: ResourceOperationVariantType.API_CALL,
isDefault: true,
resourceOperationLike: CoreResourceOperation.UPDATE,
riskLevel: ResourceOperationRiskLevel.MEDIUM,
roles: [CORE_ORG_ROLES.ORG_MEMBER],
requestDto: z.object({}),
customResponseDto: z.object({ pageCount: z.number().int().nonnegative() }),
}],
recordsUsage: {
productKey: 'rendered_pages',
quantityFromResultField: 'pageCount',
},
};
The custom implementation returns the number it actually produced:
{ "pageCount": 3 }
After successful work, the shared operation hook reads recordsUsage from the resolved operation. In an eligible organization context, this result records three units for rendered_pages, initially pending provider reporting. Reading the number from the result avoids treating the requested page count as work completed.
recordsUsage sits beside variants; it is not an input field sent by the browser. Its quantity source can instead be a fixed quantity (default one). Choose either a fixed quantity or quantityFromResultField, not both. A nested result uses a dot path such as render.pageCount.
Complete the billing chain
The scope needs a billing account and an active or trialling subscription containing that metered product. The application also needs billing/provider registration and the configured flush job. A price on a metered product alone creates no usage.
Fixed quantities describe units per successful operation. Result-derived quantities must resolve to finite non-negative numbers; zero writes nothing. An invalid result path or absent eligible subscription records nothing and logs why. The hook runs asynchronously after the operation, so its failure does not turn committed work into a request failure.
Distinguish recorded, reported and charged
| State | Meaning |
|---|---|
| Pending usage | A local quantity awaits provider reporting |
| Reported usage | The provider accepted its grouped meter event |
| Unreportable usage | The billing account no longer exists, so the quantity cannot be mapped to a provider customer |
The flush drains pending rows in pages, groups quantities according to the product policy and uses a stable event identifier for retries. A temporarily missing provider customer mapping remains retryable. Reconciliation reports quantities, not merely row counts, so an operator can see what remains pending or could never be billed.
Provider reporting is not the same as an invoice being paid. The usage dashboard’s summary read is also not the complete settlement report. Monitor failed recording and pending flush quantities as part of operating usage-based pricing.