Credit-Based license
A Credit-Based license (MeteredToken, metering mode Token) is always online. Customers share one credit wallet across all devices on the license key. Each entitled feature deducts credits according to per-feature token pricing on the product — not a flat “one use per call” like Usage-Based.
Shared wallet
One balance per license key — not per device.
Variable cost
Each feature has a TokenCost × quantity.
Usage tab
Balance, ledger, manual top-ups (owners).
When to choose Credit-Based
Choose Credit-Based when you sell a pre-paid pool of credits and different features in your product should cost different amounts. The customer starts with a balance (for example 10,000 credits). Each time they run a billable action, your app calls ConsumeAsync and the server deducts credits based on that feature’s configured price.
Think of it like a prepaid phone plan with variable call rates: one minute to country A costs 2 credits, one minute to country B costs 5 credits — same wallet, different prices per action.
Good fits
- API or SaaS with tiered actions — “10,000 API credits per month”; a simple read costs 1 credit, a heavy export costs 25.
- Document / OCR / AI products — “5,000 pages included”; OCR costs 10 credits per page, summary costs 40.
- Creative or compute tools — “1,000 render credits”; preview is cheap, 4K export is expensive.
- Top-up sales — customer buys another 5,000 credits when the wallet is low (manual grant from the Usage tab today).
How it behaves in LicenPro
- Dashboard label: Credit-Based. API enum:
MeteredToken. - Balance is shown in credits (shared across all devices on the license key).
- You must set a token cost per feature before consume works (via metering API; UI coming later).
- Example: feature
ExportPdfpriced at 25 → one consume deducts 25 credits, not 1.
When to use Usage-Based instead
If every billable action should cost exactly one use — “500 exports included”, “1,000 API calls” — and you do not need different prices per feature, use Usage-Based (MeteredCount). It is simpler: no feature pricing step.
At a glance
| Property | Value |
|---|---|
| Backend enum | LicenseType.MeteredToken (value 6) |
| Dashboard label | Credit-Based |
| Metering mode | MeteringMode.Token |
| Balance unit | credits |
| Cost per consume | FeatureMeterPricing.TokenCost × quantity |
| Activation mode | Online only — offline is not available |
| Seat limit | None — any number of devices may activate; the wallet is the limit |
Key invariant
Balance is only checked and deducted in POST /api/meter/consume. License validation, activation, and session connect never look at the balance. A Credit-Based license can activate at zero credits; your app must call ConsumeAsync when a billable feature runs and handle InsufficientBalance (HTTP 402).
Create a Credit-Based license (dashboard)
Open Licenses → Generate License. Four steps: Activation → License Type → Basic Info → Details.
Step 1 — Activation
Select Online. Credit-Based is an always-online type — the wizard forces online mode and hides metered cards if Offline is selected.
Step 2 — License type
Select the Credit-Based card (“Variable cost per feature”). Subtitle explains the shared credit pool and manual top-ups.
Step 3 — Basic info
- Product and Software release (required).
- Issued to — end user assigned to the release (required for non-perpetual types).
- License name — internal label in lists and audit.
- Optional Entitlement set — when set, only entitled features can be consumed.
Step 4 — Details
- Initial credits balance (
initialMeterBalance) — required, must be > 0 (default in the form is often 10,000). - Notes — operator context (invoice, SKU, support ticket).
On save, the backend creates a MeterWallet with mode Token and writes an InitialGrant ledger row when balance > 0.
Create Credit-Based license, initial 10,000
└─ MeterWallet { mode: Token, balance: 10000 }
└─ UsageLedger { type: InitialGrant, amount: +10000, balanceAfter: 10000 }Configure per-feature pricing (Credit-Based only)
Before clients consume a feature, set its token cost on the product. API: PUT /api/meter/features/{featureId}/pricing (product owner / admin).
TokenCostmust be > 0.- Previous active pricing rows are deactivated; history is preserved.
- Consuming a feature with no active pricing returns
PricingNotConfigured(HTTP 422).
Note: A dedicated pricing UI in the dashboard is planned; today pricing is set via API.
Activation & sessions
- Always-online — activation and sessions are required like Floating.
- No activation seat cap —
EnforceSeatLimitOnActivationis false for metered types; many devices may share one key. - Activations and sessions appear in the dashboard for support visibility (optional attribution on consume via
hardwareId/activationId).
See Activations and Sessions platform guides.
Runtime — SDK & API
Typical client flow:
var client = new LicenseClient(options);
// 1. Validate (always online — does NOT check credit balance)
var result = await client.ValidateAsync();
if (!result.IsValid) return;
// 2. Before running a billable feature — deduct credits
var consume = await client.ConsumeAsync("ExportPdf", quantity: 1);
if (!consume.Success && consume.IsInsufficientBalance)
ShowTopUpPrompt();
// 3. Optional — show remaining credits
var balance = await client.GetBalanceAsync();ConsumeAsync calls POST /api/meter/consume with product X-API-KEY. Pass an idempotency key to make retries safe — replays return the prior result without double-charging.
Consume request
| Field | Required | Notes |
|---|---|---|
licenseKey | Yes | Customer license key |
featureName | Yes | Must be entitled; must have active pricing |
idempotencyKey | Yes | Reuse on retry of the same logical operation |
quantity | No (default 1) | Cost = TokenCost × quantity |
hardwareId | No | Auto-detected by SDK when omitted |
activationId | No | Attribute usage to a device row |
Worked example
- Create license with initial 10,000 credits.
- Price feature
"render"at TokenCost 40. - SDK consumes
render×1 → cost 40 → balance 9,960. - Retry with same
idempotencyKey→ replay, balance still 9,960. - Consume unpriced feature →
PricingNotConfigured(422). - Owner grants +5,000 → balance 14,960, ledger
AdminGrant.
Usage tab (license detail)
Open a Credit-Based license → Usage tab.
| Role | What you see |
|---|---|
| Product owner / Admin | Remaining balance, Grant balance form (amount, reason, external reference), full usage ledger |
| Assigned end user (My Licenses → detail) | Read-only balance card; ledger without grant actions |
| Member / Viewer | No grant UI; read-only where permitted |
Ledger entry types: InitialGrant, Consume (negative amount), AdminGrant, Adjust.
Top-ups are manual only — there is no payment gateway integration in the current release.
Analytics
Organization analytics includes a metered usage section from GET /api/statistics/meter-usage: metered license counts, total balance remaining, consumed/granted in the period, low-balance alerts, daily consumption trend, top features, and top licenses.
Consume error codes
| ErrorCode | HTTP | Meaning |
|---|---|---|
InvalidRequest | 400 | Missing key, feature, or idempotency key |
LicenseNotFound | 404 | No license for the key |
NotMeteredLicense | 400 | Wrong license type |
LicenseInvalid | 400 | Status is not Valid |
FeatureNotEntitled | 403 | Feature not in entitlement sets (when sets are configured) |
WalletNotFound | 400 | Wallet missing |
PricingNotConfigured | 422 | No active TokenCost for this feature |
InsufficientBalance | 402 | balance < cost |
ConcurrencyConflict | 409 | Retry the consume call |
Credit-Based vs Usage-Based
Use this quick guide if you are deciding between the two metered types:
| Question | Credit-Based | Usage-Based |
|---|---|---|
| What are you selling? | A credit wallet (e.g. “10,000 credits”) | A number of actions (e.g. “500 exports”) |
| Cost per action | Varies by feature — you set each feature’s token price | Always the same — usually 1 use per consume |
| Setup before first consume | Configure TokenCost per feature | Nothing extra — just create the license with an initial use count |
| Best analogy | Prepaid credits with different prices per service | “Includes 500 uses” — each button click counts as one |
