Billing Cycle Management Service Reference
Service Overview
Billing cycles define how plans renew (duration, cadence, and external price IDs). Each cycle belongs to a plan, exposes derived planKey/productKey in DTOs, and enforces delete guards whenever subscriptions or plan transitions reference it.
- Duration units:
days,weeks,months,years, orforever(whenforever,durationValuemust be omitted). - Cycles can expose
externalProductId(e.g., Stripe price) for payment processor mappings. - Delete operations require the cycle to be archived and unused by subscriptions or plan transition settings.
Accessing the Service
Method Catalog
| Method | Description | Returns |
|---|---|---|
createBillingCycle | Creates a cycle for an existing plan | Promise<BillingCycleDto> |
updateBillingCycle | Updates mutable fields on a cycle | Promise<BillingCycleDto> |
getBillingCycle | Retrieves a cycle by key | Promise<BillingCycleDto \| null> |
getBillingCyclesByPlan | Lists cycles for a plan | Promise<BillingCycleDto[]> |
listBillingCycles | Lists cycles with filters/pagination | Promise<BillingCycleDto[]> |
archiveBillingCycle | Archives a cycle | Promise<void> |
unarchiveBillingCycle | Reactivates an archived cycle | Promise<void> |
deleteBillingCycle | Deletes an archived, unused cycle | Promise<void> |
calculateNextPeriodEnd | Computes next renewal end date | Promise<Date \| null> |
getBillingCyclesByDurationUnit | Filters cycles by duration unit | Promise<BillingCycleDto[]> |
getDefaultBillingCycles | Loads pre-installed defaults (monthly/quarterly/yearly) | Promise<BillingCycleDto[]> |
| Method | Description | Returns |
|---|---|---|
CreateBillingCycleAsync | Creates a cycle for an existing plan | Task<BillingCycleDto> |
UpdateBillingCycleAsync | Updates mutable fields on a cycle | Task<BillingCycleDto> |
GetBillingCycleAsync | Retrieves a cycle by key | Task<BillingCycleDto?> |
GetBillingCyclesByPlanAsync | Lists cycles for a plan | Task<List<BillingCycleDto>> |
ListBillingCyclesAsync | Lists cycles with filters/pagination | Task<List<BillingCycleDto>> |
ArchiveBillingCycleAsync | Archives a cycle | Task |
UnarchiveBillingCycleAsync | Reactivates an archived cycle | Task |
DeleteBillingCycleAsync | Deletes an archived, unused cycle | Task |
CalculateNextPeriodEndAsync | Computes next renewal end date | Task<DateTime?> |
GetBillingCyclesByDurationUnitAsync | Filters cycles by duration unit | Task<List<BillingCycleDto>> |
GetDefaultBillingCyclesAsync | Loads pre-installed defaults (monthly/quarterly/yearly) | Task<List<BillingCycleDto>> |
Method Reference
createBillingCycle
Description
Validates a new billing cycle payload, ensures the plan exists, and persists the cycle with active status.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
dto | CreateBillingCycleDto | Yes | Cycle definition for an existing plan. |
Input Properties
| Field | Type | Required | Description |
|---|---|---|---|
planKey | string | Yes | Plan owning the cycle (lowercase alphanumeric + -). |
key | string | Yes | Globally unique billing cycle key. |
displayName | string | Yes | 1–255 char label. |
description | string | No | ≤1000 chars. |
durationValue | number | Conditional | Required unless durationUnit is forever; positive integer. |
durationUnit | 'days' \| 'weeks' \| 'months' \| 'years' \| 'forever' | Yes | Renewal cadence. |
externalProductId | string | No | Stripe price or other external ID (≤255 chars). |
| Property | Type | Required | Description |
|---|---|---|---|
PlanKey | string | Yes | Plan owning the cycle. |
Key | string | Yes | Globally unique billing cycle key. |
DisplayName | string | Yes | 1–255 char label. |
Description | string | No | ≤1000 chars. |
DurationValue | int? | Conditional | Required unless DurationUnit is forever. |
DurationUnit | string | Yes | days, weeks, months, years, or forever. |
ExternalProductId | string | No | Stripe price or other external ID (≤255 chars). |
Returns
Promise<BillingCycleDto> – persisted cycle snapshot.
Task<BillingCycleDto> – persisted cycle snapshot.
Return Properties
| Field | Type | Description |
|---|---|---|
key | string | Cycle key. |
planKey | string | Owning plan key. |
productKey | string | Derived from plan. |
displayName | string | Display label. |
description | string \| null | Optional description. |
status | string | active or archived. |
durationValue | number \| null | null when unit is forever. |
durationUnit | string | Duration unit. |
externalProductId | string \| null | Payment processor price ID. |
createdAt | string | ISO timestamp. |
updatedAt | string | ISO timestamp. |
| Property | Type | Description |
|---|---|---|
Key | string | Cycle key. |
PlanKey | string | Owning plan key. |
ProductKey | string | Derived from plan. |
DisplayName | string | Display label. |
Description | string? | Optional description. |
Status | string | active or archived. |
DurationValue | int? | null when unit is forever. |
DurationUnit | string | Duration unit. |
ExternalProductId | string? | Payment processor price ID. |
CreatedAt | string | ISO timestamp. |
UpdatedAt | string | ISO timestamp. |
Expected Results
- Validates DTO (including duration rules).
- Loads plan by
planKeyand fails if missing. - Rejects duplicate billing cycle keys.
- Persists cycle with status
active.
Potential Errors
| Error | When |
|---|---|
ValidationError | DTO invalid or duration config inconsistent. |
NotFoundError | Plan missing. |
ConflictError | Billing cycle key already exists. |
Example
updateBillingCycle
Description
Updates mutable fields (display name, description, duration config, pricing metadata) on an existing cycle.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Cycle key to update. |
dto | UpdateBillingCycleDto | Yes | Partial update object. |
Input Properties
All fields mirror CreateBillingCycleDto but are optional. If durationUnit is set to forever, durationValue must be omitted.
All properties mirror CreateBillingCycleDto but are optional. If DurationUnit is set to forever, DurationValue must be omitted.
Returns
Promise<BillingCycleDto> – updated cycle snapshot.
Task<BillingCycleDto> – updated cycle snapshot.
Return Properties
- Same
BillingCycleDtofields described increateBillingCycle.
- Same
BillingCycleDtofields described increateBillingCycle.
Expected Results
- Validates DTO.
- Loads cycle, applies permissible fields, saves.
Example
Potential Errors
| Error | When |
|---|---|
ValidationError | DTO invalid. |
NotFoundError | Cycle missing. |
getBillingCycle
Description
Retrieves a single billing cycle by key (returns null if not found).
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Cycle key. |
Returns
Promise<BillingCycleDto | null>
Task<BillingCycleDto?>
Return Properties
BillingCycleDtoshape (seecreateBillingCycle) ornullwhen not found.
BillingCycleDtoshape (seecreateBillingCycle) ornullwhen not found.
Expected Results
- Loads cycle; if stored plan reference is missing (data corruption), throws
NotFoundError.
Potential Errors
| Error | When |
|---|---|
NotFoundError | Cycle missing or plan reference cannot be resolved. |
Example
getBillingCyclesByPlan
Description
Lists all billing cycles belonging to a plan.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
planKey | string | Yes | Plan identifier. |
Returns
Promise<BillingCycleDto[]>
Task<List<BillingCycleDto>>
Return Properties
- Array of
BillingCycleDtoentries scoped to the plan.
List<BillingCycleDto>scoped to the plan.
Expected Results
- Ensures plan exists.
- Returns all cycles mapped to the plan (with derived product key).
Potential Errors
| Error | When |
|---|---|
NotFoundError | Plan missing. |
Example
listBillingCycles
Description
Paginates billing cycles with optional filters.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
filters | BillingCycleFilterDto | No | Status, duration unit, plan key, search, pagination, sorting. |
Input Properties
| Field | Type | Description |
|---|---|---|
planKey | string | Limit to a plan. |
status | 'active' or 'archived' | Filter by state. |
durationUnit | 'days', 'weeks', 'months', 'years', 'forever' | Filter by unit. |
search | string | Text search across key/display name. |
limit | number | 1–100 (default 50). |
offset | number | ≥0 (default 0). |
sortBy | 'displayName' or 'createdAt' | Sort column. |
sortOrder | 'asc' or 'desc' | Sort direction, default 'asc'. |
| Property | Type | Description |
|---|---|---|
PlanKey | string | Limit to a plan. |
Status | string | active or archived. |
DurationUnit | string | Filter by unit. |
Search | string | Text search across key/display name. |
Limit | int | 1–100 (default 50). |
Offset | int | ≥0 (default 0). |
SortBy | BillingCycleSortBy | Sort column. |
SortOrder | SortOrder | Sort direction, default asc. |
Returns
Promise<BillingCycleDto[]>
Task<List<BillingCycleDto>>
Return Properties
- Array of
BillingCycleDtoentries respecting the supplied filters.
List<BillingCycleDto>respecting the supplied filters.
Expected Results
- Validates filters.
- Executes query, returning DTO array (same schema as
createBillingCycleresult).
Potential Errors
| Error | When |
|---|---|
ValidationError | Filters invalid. |
Example
archiveBillingCycle
Description
Marks a billing cycle as archived (cannot be used for new subscriptions).
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Cycle key. |
Returns
Promise<void>
Task
Return Properties
- None.
- None.
Expected Results
- Loads cycle, sets status
archived, saves.
Potential Errors
| Error | When |
|---|---|
NotFoundError | Cycle missing. |
Example
unarchiveBillingCycle
Description
Restores an archived cycle to active.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Cycle key. |
Returns
Promise<void>
Task
Return Properties
- None.
- None.
Expected Results
- Loads cycle, sets status
active, saves.
Potential Errors
| Error | When |
|---|---|
NotFoundError | Cycle missing. |
Example
deleteBillingCycle
Description
Permanently deletes a billing cycle after ensuring it is archived and unused by subscriptions or plan transitions.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Cycle to delete. |
Returns
Promise<void>
Task
Return Properties
- None.
- None.
Expected Results
- Loads cycle, calls
billingCycle.canDelete()(requires archived status). - Verifies no subscriptions reference the cycle.
- Ensures no plan has
onExpireTransitionToBillingCycleKeypointing to it. - Deletes record.
Potential Errors
| Error | When |
|---|---|
NotFoundError | Cycle missing. |
DomainError | Cycle still active or referenced. |
Example
calculateNextPeriodEnd
Description
Computes the next period end for a billing cycle, given the current period end.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
billingCycleKey | string | Yes | Cycle to use for calculation. |
currentPeriodEnd | Date | Yes | Current period end date. |
Returns
Promise<Date | null> – null for forever cycles.
Task<DateTime?> – null for forever cycles.
Return Properties
Date: calculated next period end.null: returned when the cycle duration unit isforever.
DateTime: calculated next period end.null: returned when the cycle duration unit isforever.
Expected Results
- Loads cycle, applies duration arithmetic (e.g., add N months) or returns
nullwhen unit isforever.
Potential Errors
| Error | When |
|---|---|
NotFoundError | Cycle missing. |
Example
getBillingCyclesByDurationUnit
Description
Provides all cycles already stored with a specific duration unit.
Signature
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
durationUnit | DurationUnit | Yes | 'days', 'weeks', 'months', 'years', or 'forever'. |
Returns
Promise<BillingCycleDto[]>
Task<List<BillingCycleDto>>
Return Properties
- Array of
BillingCycleDtoentries limited to the requested duration unit.
List<BillingCycleDto>limited to the requested duration unit.
Expected Results
- Filters existing cycles by unit (no errors thrown).
Example
getDefaultBillingCycles
Description
Retrieves pre-installed cycles (monthly/quarterly/yearly) when present.
Signature
Returns
Promise<BillingCycleDto[]>
Task<List<BillingCycleDto>>
Return Properties
- Array of default
BillingCycleDtoentries that were seeded (or empty).
List<BillingCycleDto>of defaults that were seeded (or empty).
Expected Results
- Attempts to load keys such as
monthly,quarterly,yearly; returns whichever exist.
Potential Errors
- None (returns empty array when defaults not installed).
Example
Related Workflows
- Plans must exist before creating billing cycles (
PlanManagementService). - Subscriptions reference billing cycles; deletion is blocked when subscriptions are present (
SubscriptionManagementService). - Stripe integration uses
externalProductIdto map cycles to Stripe prices (StripeIntegrationService).