Add-ons
Purpose
Add-ons are reusable packages of feature values for a product. A package can affect several features, such as seats and storage, and can be attached to multiple subscriptions. Define contributions here; attach packages through Subscriptions. For an individual exception, see overrides or add-ons.
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 |
|---|---|
createAddon | Creates an add-on and its contributions. |
updateAddon | Updates an add-on and selected contributions. |
getAddon | Gets an add-on or null. |
listAddons | Lists a product's add-ons. |
archiveAddon | Stops new attachments. |
unarchiveAddon | Allows attachments again. |
deleteAddon | Deletes an unused archived add-on. |
| Method | Purpose |
|---|---|
CreateAddonAsync | Creates an add-on and its contributions. |
UpdateAddonAsync | Updates an add-on and selected contributions. |
GetAddonAsync | Gets an add-on or null. |
ListAddonsAsync | Lists a product's add-ons. |
ArchiveAddonAsync | Stops new attachments. |
UnarchiveAddonAsync | Allows attachments again. |
DeleteAddonAsync | Deletes an unused archived add-on. |
Method details
createAddon
Create an active add-on with a globally unique key. The definition and all contributions are saved together; invalid contributions cancel the operation. Each contributed feature must be associated with the add-on's product.
Parameters
input: CreateAddonDto containing the product, label, and feature contributions.
Returns AddonDto: The saved definition, including its complete feature-value map.
Example
// studio must be active, with an associated numeric seats feature.
await subscrio.addons.createAddon({
key: 'seat-pack',
productKey: 'studio',
displayName: 'Extra seats',
featureValues: { seats: '3' }
});
Errors (3)
ValidationError: A key, label, mode, priority, or feature value is invalid.NotFoundError: The product is missing or inactive, or a feature is not associated with it.ConflictError: The add-on key already exists.
Parameters
input: CreateAddonDto containing the product, label, and feature contributions.
Returns AddonDto: The saved definition, including its complete feature-value map.
Example
// studio must be active, with an associated numeric seats feature.
await subscrio.Addons.CreateAddonAsync(new CreateAddonDto(
Key: "seat-pack",
ProductKey: "studio",
DisplayName: "Extra seats",
FeatureValues: new() { ["seats"] = "3" }));
Errors (3)
ValidationException: A key, label, mode, priority, or feature value is invalid.NotFoundException: The product is missing or inactive, or a feature is not associated with it.ConflictException: The add-on key already exists.
updateAddon
Update an add-on without changing its key or product. Supplied feature entries add, replace, or remove individual contributions; other entries are retained. Definition and contribution changes commit together. Switching to replacement mode requires every active attachment to have quantity one.
Parameters
addonKey: Add-on to update.input: UpdateAddonDto. Uses partial updates; feature-map entries have their own removal rules.
Returns AddonDto: The saved definition, including its complete feature-value map.
Example
// seat-pack exists; seats and storage are associated with its product.
await subscrio.addons.updateAddon('seat-pack', {
featureValues: { seats: '5', storage: null }
});
Errors (3)
ValidationError: A supplied property or contribution is invalid.NotFoundError: The add-on or an associated feature is missing.ConflictError: Replacement mode conflicts with an active attachment quantity.
Parameters
key: Add-on to update.input: UpdateAddonDto. Uses partial updates; feature-map entries have their own removal rules.
Returns AddonDto: The saved definition, including its complete feature-value map.
Example
// seat-pack exists; seats and storage are associated with its product.
await subscrio.Addons.UpdateAddonAsync("seat-pack", new UpdateAddonDto(
FeatureValues: new() { ["seats"] = "5", ["storage"] = null }));
Errors (3)
ValidationException: A supplied property or contribution is invalid.NotFoundException: The add-on or an associated feature is missing.ConflictException: Replacement mode conflicts with an active attachment quantity.
getAddon
Retrieve one add-on definition, including archived definitions.
Parameters
addonKey: Add-on key.
Returns AddonDto | null: Definition and complete contributions, or null when the key is missing.
Example
Parameters
key: Add-on key.
Returns AddonDto?: Definition and complete contributions, or null when the key is missing.
Example
listAddons
List a product's add-ons in ascending key order. Both active and archived definitions are included unless filtered. TypeScript also supports searching by add-on key.
Parameters
productKey: Product whose add-ons to retrieve.filter: Optional PageFilter. Defaults to 50 results at offset zero.
Returns AddonDto[]: Matching definitions and contributions; empty when no results or product exist.
Example
const addons = await subscrio.addons.listAddons('studio', { status: 'active' });
console.log(addons);
Errors (1)
ValidationError: Pagination is outside the allowed range.
Parameters
productKey: Product whose add-ons to retrieve.limit: Optional page size, 1 to 500; defaults to 50.offset: Optional nonnegative number of records to skip; defaults to zero.status: Optional status filter; defaults to null, which includes all statuses.
Returns List<AddonDto>: Matching definitions and contributions; empty when no results or product exist.
Example
var addons = await subscrio.Addons.ListAddonsAsync("studio", status: "active");
Console.WriteLine(addons.Count);
Errors (1)
ValidationException: Pagination is outside the allowed range.
archiveAddon
Archive the add-on to prevent new attachments. Existing attachments and their contributions remain; archive does not detach subscriptions.
Parameters
k: Add-on key.
Returns No returned value.
Example
Errors (1)
NotFoundError: The add-on does not exist.
unarchiveAddon
Restore the add-on to active status so it can be attached again. Existing definitions and attachments are retained.
Parameters
k: Add-on key.
Returns No returned value.
Example
Errors (1)
NotFoundError: The add-on does not exist.
deleteAddon
Permanently delete an archived add-on and its feature contributions. Any attachment history blocks deletion, including cancelled attachments.
Parameters
k: Add-on key.
Returns No returned value.
Example
// seat-pack must exist and be archived with no attachment history.
await subscrio.addons.deleteAddon('seat-pack');
Errors (2)
NotFoundError: The add-on does not exist.ConflictError: The add-on is active or has attachment history.
Parameters
key: Add-on key.
Returns No returned value.
Example
// seat-pack must exist and be archived with no attachment history.
await subscrio.Addons.DeleteAddonAsync("seat-pack");
Errors (2)
NotFoundException: The add-on does not exist.ConflictException: The add-on is active or has attachment history.
Data types
For input types, Required means the caller must supply the property. For returned types, it means the property is present; nullability is shown separately.
CreateAddonDto
Properties used to define an add-on.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
key | string | Yes | None | Globally unique add-on key; cannot be changed. |
productKey | string | Yes | None | Owning product; cannot be changed. |
displayName | string | Yes | None | Nonblank label, at most 255 characters. |
description | string | undefined | No | None | Optional description. |
compositionMode | "additive" | "override" | undefined | No | additive | Add contributions to the base value, or replace it. Replacement attachments require quantity one. |
priority | number | undefined | No | 0 | Lower values win when choosing between replacements. .NET uses a 32-bit integer; TypeScript accepts integers from -2,147,483,647 to 2,147,483,647. |
metadata | Record<string, unknown> | undefined | No | None | Application-defined metadata. |
featureValues | Record<string, string> | undefined | No | None | Associated feature keys mapped to contributions, stored as strings and validated for the feature type. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
Key | string | Yes | None | Globally unique add-on key; cannot be changed. |
ProductKey | string | Yes | None | Owning product; cannot be changed. |
DisplayName | string | Yes | None | Nonblank label, at most 255 characters. |
Description | string? | No | null | Optional description. |
CompositionMode | string | No | additive | Add contributions to the base value, or replace it. Replacement attachments require quantity one. |
Priority | int | No | 0 | Lower values win when choosing between replacements. .NET uses a 32-bit integer; TypeScript accepts integers from -2,147,483,647 to 2,147,483,647. |
Metadata | Dictionary<string, object?>? | No | null | Application-defined metadata. |
FeatureValues | Dictionary<string, string>? | No | null | Associated feature keys mapped to contributions, stored as strings and validated for the feature type. |
AddonDto
Complete add-on definition. Products and plans include their product's catalog; features include contributing add-ons, and subscriptions include attached definitions.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
key | string | Yes | Not applicable | Globally unique add-on key; cannot be changed. |
productKey | string | Yes | Not applicable | Owning product; cannot be changed. |
displayName | string | Yes | Not applicable | Nonblank label, at most 255 characters. |
description | string | undefined | No | Not applicable | Optional description. |
compositionMode | "additive" | "override" | Yes | Not applicable | Add contributions to the base value, or replace it. Replacement attachments require quantity one. |
priority | number | Yes | Not applicable | Lower values win when choosing between replacements. .NET uses a 32-bit integer; TypeScript accepts integers from -2,147,483,647 to 2,147,483,647. |
metadata | Record<string, unknown> | undefined | No | Not applicable | Application-defined metadata. |
featureValues | Record<string, string> | Yes | Not applicable | Associated feature keys mapped to contributions, stored as strings and validated for the feature type. |
status | "active" | "archived" | Yes | Not applicable | Catalog status. |
createdAt | string | Yes | Not applicable | Creation time in UTC. |
updatedAt | string | Yes | Not applicable | Last update time in UTC. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
Key | string | Yes | Not applicable | Globally unique add-on key; cannot be changed. |
ProductKey | string | Yes | Not applicable | Owning product; cannot be changed. |
DisplayName | string | Yes | Not applicable | Nonblank label, at most 255 characters. |
Description | string? | Yes | Not applicable | Optional description. |
CompositionMode | string | Yes | Not applicable | Add contributions to the base value, or replace it. Replacement attachments require quantity one. |
Priority | int | Yes | Not applicable | Lower values win when choosing between replacements. .NET uses a 32-bit integer; TypeScript accepts integers from -2,147,483,647 to 2,147,483,647. |
Metadata | Dictionary<string, object?>? | Yes | Not applicable | Application-defined metadata. |
FeatureValues | Dictionary<string, string> | Yes | Not applicable | Associated feature keys mapped to contributions, stored as strings and validated for the feature type. |
Status | string | Yes | Not applicable | Catalog status. |
CreatedAt | string | Yes | Not applicable | Creation time in UTC. |
UpdatedAt | string | Yes | Not applicable | Last update time in UTC. |
UpdateAddonDto
Editable add-on properties. Feature contributions are patched per key; metadata is replaced as a whole.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
displayName | string | undefined | No | None | Nonblank label, at most 255 characters. |
description | string | undefined | No | None | Optional description. |
compositionMode | "additive" | "override" | undefined | No | None | Add contributions to the base value, or replace it. Replacement attachments require quantity one. |
priority | number | undefined | No | None | Lower values win when choosing between replacements. .NET uses a 32-bit integer; TypeScript accepts integers from -2,147,483,647 to 2,147,483,647. |
metadata | Record<string, unknown> | undefined | No | None | Replaces the saved metadata object. An empty object clears its entries. |
featureValues | Record<string, string | null> | undefined | No | None | Omit to keep all contributions. Supplied entries add or replace values; null removes a key. An empty map makes no changes. A null map is rejected. |
| Property | Type | Required | Default | Meaning |
|---|---|---|---|---|
DisplayName | string? | No | null | Nonblank label, at most 255 characters. |
Description | string? | No | null | Optional description. |
CompositionMode | string? | No | null | Add contributions to the base value, or replace it. Replacement attachments require quantity one. |
Priority | int? | No | null | Lower values win when choosing between replacements. .NET uses a 32-bit integer; TypeScript accepts integers from -2,147,483,647 to 2,147,483,647. |
Metadata | Dictionary<string, object?>? | No | null | Replaces the saved metadata object. An empty object clears its entries. |
FeatureValues | Dictionary<string, string?>? | No | null | Omit to keep all contributions. Supplied entries add or replace values; null removes a key. An empty map makes no changes. A null map also makes no changes. |
PageFilter
TypeScript pagination and filtering options. .NET takes pagination and status as individual method arguments and has no search argument.
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
limit | number | No | 50 | Integer page size, 1 to 500. |
offset | number | No | 0 | Nonnegative safe integer; number of rows to skip. |
search | string | No | None | Case-insensitive key pattern; SQL wildcard characters apply. |
status | string | No | None | Filter by active or archived status. |
No PageFilter DTO is used by this method. See the parameters of ListAddonsAsync.
Related guides
- Overrides or subscription add-ons: choose an exception or reusable package.
- How Feature Values Are Calculated: combine plan values, add-ons, and overrides.
- Subscriptions: attach or detach an add-on.
- Extending Subscrio: software extensions are separate from subscription add-ons.