Metered Usage
Purpose
Metered Usage tracks consumption of metered features. Configure reset periods, enforcement, aggregation, and whether usage is shared by a customer or tracked per subscription on the feature.
Access and initialization
Access
Method catalog
Database and connection failures may propagate from any operation. Method-specific errors are listed with each method.
| Method | Purpose |
|---|---|
getUsage | Reads allowance and checks a proposed amount. |
reportUsage | Atomically records accepted usage. |
listUsageEvents | Lists accepted usage-event snapshots. |
| Method | Purpose |
|---|---|
GetUsageAsync | Reads allowance and checks a proposed amount. |
ReportUsageAsync | Atomically records accepted usage. |
ListUsageEventsAsync | Lists accepted usage-event snapshots. |
Method details
getUsage
Read the current period's allowance and consumption, and check a proposed amount without recording it. The result can change before a later write; reporting usage performs the authoritative limit check.
Parameters
customerKey: Customer key.productKey: Product key.featureKey: Associated metered feature key.options: Optional UsageOptions; checks one unit by default.
Returns UsageDto: Current balance, projected consumption, and access decision.
Example
// api-calls is customer-scoped and associated with saas.
const usage = await subscrio.metering.getUsage('acme', 'saas', 'api-calls', {
requestedUsage: 5
});
console.log(usage.hasAccess, usage.remaining);
Errors (3)
NotFoundError: The customer, associated metered feature, or matching subscription is missing.ValidationError: The amount, usage scope, or resolved limit is invalid.MeteringPeriodError: A billing-period reset has missing or stale subscription period dates.
Parameters
customerKey: Customer key.productKey: Product key.featureKey: Associated metered feature key.options: Optional UsageOptions; checks one unit by default.
Returns UsageDto: Current balance, projected consumption, and access decision.
Example
// api-calls is customer-scoped and associated with saas.
var usage = await subscrio.Metering.GetUsageAsync("acme", "saas", "api-calls",
new UsageOptions(RequestedUsage: 5));
Console.WriteLine($"Allowed: {usage.HasAccess}, remaining: {usage.Remaining}");
Errors (3)
NotFoundException: The customer, associated metered feature, or matching subscription is missing.ValidationException: The amount, usage scope, or resolved limit is invalid.MeteringPeriodException: A billing-period reset has missing or stale subscription period dates.
reportUsage
Record consumption and an event in one transaction. Hard enforcement rejects amounts above the limit; soft enforcement records the overage. Both require an eligible, unarchived subscription. Count aggregation accepts exactly one unit per report.
Retry the same customer-scoped idempotency key with the identical request to receive the original snapshot without charging again, even in a later period. Changing the request under that key fails. Denied attempts create no usage event. Before-hooks run within the transaction; after-hooks run after commit and are not replayed.
Parameters
customerKey: Customer key.productKey: Product key.featureKey: Associated metered feature key.quantity: Positive integer, at most 9,007,199,254,740,991. Count aggregation requires 1.options: UsageReportOptions, including a stable idempotency key.
Returns UsageReportDto: Accepted event and post-write usage snapshot; a retry returns the original result.
Example
// acme has an eligible subscription; api-calls uses customer scope and count aggregation.
const report = await subscrio.metering.reportUsage('acme', 'saas', 'api-calls', 1, {
idempotencyKey: 'request-123'
});
console.log(report.usage.consumed);
Errors (5)
NotFoundError: The customer, associated metered feature, or matching subscription is missing.ValidationError: The amount, usage scope, or resolved limit is invalid.MeteringPeriodError: A billing-period reset has missing or stale subscription period dates.IdempotencyConflictError: The key was used for a different request.UsageLimitExceededError: The hard limit would be exceeded or no eligible subscription exists; the error includes the usage decision.
Parameters
customerKey: Customer key.productKey: Product key.featureKey: Associated metered feature key.quantity: Positive integer, at most 9,007,199,254,740,991. Count aggregation requires 1.options: UsageReportOptions, including a stable idempotency key.
Returns UsageReportDto: Accepted event and post-write usage snapshot; a retry returns the original result.
Example
// acme has an eligible subscription; api-calls uses customer scope and count aggregation.
var report = await subscrio.Metering.ReportUsageAsync("acme", "saas", "api-calls", 1,
new UsageReportOptions(IdempotencyKey: "request-123"));
Console.WriteLine(report.Usage.Consumed);
Errors (5)
NotFoundException: The customer, associated metered feature, or matching subscription is missing.ValidationException: The amount, usage scope, or resolved limit is invalid.MeteringPeriodException: A billing-period reset has missing or stale subscription period dates.IdempotencyConflictException: The key was used for a different request.UsageLimitExceededException: The hard limit would be exceeded or no eligible subscription exists; the error includes the usage decision.
listUsageEvents
List accepted event snapshots, newest first with event ID as a tie-breaker. These are the saved post-write results, not recalculated current balances. Date filters include the lower bound and exclude the upper bound.
Parameters
customerKey: Customer key.productKey: Product key.featureKey: Associated metered feature key.filter: Optional UsageHistoryFilter. Defaults to 50 events at offset zero.
Returns UsageReportDto[]: Saved event snapshots, or an empty collection when none match.
Example
const events = await subscrio.metering.listUsageEvents('acme', 'saas', 'api-calls', {
limit: 20, offset: 0
});
console.log(events);
Errors (1)
ValidationError: Pagination is invalid.
Parameters
customerKey: Customer key.productKey: Product key.featureKey: Associated metered feature key.limit: Optional page size, 1 to 500; defaults to 50.offset: Optional nonnegative rows to skip; defaults to 0.subscriptionKey: Optional subscription filter; null includes all subscriptions and customer-scoped events.from,to: Optional UTC event-time bounds; default null.
Returns List<UsageReportDto>: Saved event snapshots, or an empty collection when none match.
Example
var events = await subscrio.Metering.ListUsageEventsAsync(
"acme", "saas", "api-calls", limit: 20);
Console.WriteLine(events.Count);
Errors (1)
ValidationException: Pagination is invalid.
Data types
All amounts are integers within the shared safe range, 0 to 9,007,199,254,740,991, unless a parameter requires a positive amount. Required means supplied input or a guaranteed output property. Metering configuration is documented on Features.
UsageOptions
Options for a read-only allowance check.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
subscriptionKey | string | undefined | No | None | Required for subscription-scoped usage; omit for customer-scoped usage. |
requestedUsage | number | undefined | No | 1 | Nonnegative proposed amount; zero reads the balance without projecting additional usage. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
SubscriptionKey | string? | No | null | Required for subscription-scoped usage; omit for customer-scoped usage. |
RequestedUsage | long | No | 1 | Nonnegative proposed amount; zero reads the balance without projecting additional usage. |
UsageDto
Current or saved period balance and access decision.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
hasAccess | boolean | Yes | Not applicable | True when an eligible subscription exists and enforcement permits the requested amount. |
limit | number | Yes | Not applicable | Resolved feature allowance for this period. |
consumed | number | Yes | Not applicable | Amount already recorded. |
remaining | number | Yes | Not applicable | Allowance minus consumption, clamped to zero. |
requestedUsage | number | Yes | Not applicable | Amount checked; zero in a report result. |
projectedConsumed | number | Yes | Not applicable | Consumption plus requested usage. |
isOverage | boolean | Yes | Not applicable | True when projected consumption exceeds the limit. |
enforcement | "hard" | "soft" | Yes | Not applicable | hard rejects overage; soft permits it. |
usageScope | "customer" | "subscription" | Yes | Not applicable | customer shares a balance across the product; subscription tracks each subscription separately. |
subscriptionKey | string | undefined | No | Not applicable | Subscription key for subscription-scoped usage; omitted or null otherwise. |
periodStart | string | Yes | Not applicable | Inclusive UTC start of the usage period. |
periodEnd | string | Yes | Not applicable | Exclusive UTC end of the usage period. |
accessDeniedReason | "limit_exceeded" | "no_active_subscription" | undefined | No | Not applicable | limit_exceeded or no_active_subscription when access is denied; otherwise absent or null. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
HasAccess | bool | Yes | Not applicable | True when an eligible subscription exists and enforcement permits the requested amount. |
Limit | long | Yes | Not applicable | Resolved feature allowance for this period. |
Consumed | long | Yes | Not applicable | Amount already recorded. |
Remaining | long | Yes | Not applicable | Allowance minus consumption, clamped to zero. |
RequestedUsage | long | Yes | Not applicable | Amount checked; zero in a report result. |
ProjectedConsumed | long | Yes | Not applicable | Consumption plus requested usage. |
IsOverage | bool | Yes | Not applicable | True when projected consumption exceeds the limit. |
Enforcement | string | Yes | Not applicable | hard rejects overage; soft permits it. |
UsageScope | string | Yes | Not applicable | customer shares a balance across the product; subscription tracks each subscription separately. |
SubscriptionKey | string? | Yes | Not applicable | Subscription key for subscription-scoped usage; omitted or null otherwise. |
PeriodStart | string | Yes | Not applicable | Inclusive UTC start of the usage period. |
PeriodEnd | string | Yes | Not applicable | Exclusive UTC end of the usage period. |
AccessDeniedReason | string? | Yes | Not applicable | limit_exceeded or no_active_subscription when access is denied; otherwise absent or null. |
UsageReportOptions
Identity and context for a usage write.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
idempotencyKey | string | Yes | None | Nonblank retry key, 1 to 255 characters, unique across usage reports for this customer. |
subscriptionKey | string | undefined | No | None | Required for subscription-scoped usage; omit for customer-scoped usage. |
metadata | Record<string, unknown> | undefined | No | None | Optional JSON metadata included in request identity; not returned in the event DTO. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
IdempotencyKey | string | Yes | None | Nonblank retry key, 1 to 255 characters, unique across usage reports for this customer. |
SubscriptionKey | string? | No | null | Required for subscription-scoped usage; omit for customer-scoped usage. |
Metadata | Dictionary<string, object?>? | No | null | Optional JSON metadata included in request identity; not returned in the event DTO. |
UsageReportDto
Persisted result of an accepted usage report.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
eventId | string | Yes | Not applicable | Opaque event identifier represented as a string. |
idempotencyKey | string | Yes | Not applicable | Original retry key. |
quantity | number | Yes | Not applicable | Accepted quantity after before-hook adjustments. |
recordedAt | string | Yes | Not applicable | UTC event timestamp. |
usage | UsageDto | Yes | Not applicable | Post-write usage snapshot. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
EventId | string | Yes | Not applicable | Opaque event identifier represented as a string. |
IdempotencyKey | string | Yes | Not applicable | Original retry key. |
Quantity | long | Yes | Not applicable | Accepted quantity after before-hook adjustments. |
RecordedAt | string | Yes | Not applicable | UTC event timestamp. |
Usage | UsageDto | Yes | Not applicable | Post-write usage snapshot. |
UsageHistoryFilter
TypeScript event-history filters. .NET accepts these values as individual method arguments.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
subscriptionKey | string | undefined | No | None | Filter one subscription; omit to include all scopes. |
from | string | undefined | No | None | Inclusive UTC start, as an ISO timestamp. |
to | string | undefined | No | None | Exclusive UTC end, as an ISO timestamp. |
limit | number | undefined | No | 50 | Page size, 1 to 500. |
offset | number | undefined | No | 0 | Nonnegative rows to skip. |
search | string | undefined | No | None | Inherited from PageFilter but ignored by this method. |
status | string | undefined | No | None | Inherited from PageFilter but ignored by this method. |
No separate .NET DTO. See ListUsageEventsAsync.
Related guides
- Features: configure metering.
- How Feature Values Are Calculated: derive allowance from plans, add-ons, and overrides.
- Subscriptions: maintain billing-period dates.
- Credits: charge prepaid credits for actions.