Skip to main content

What a product is

A product is the core catalog object in Zenskar. It defines what you sell. Pricing presets attached to a product define how it is priced and billed. Keeping these two separate means the same product can carry different pricing across different contracts, without duplicating the underlying catalog entry. The rest of this page covers each component of a product: type and product subtype, pricing and its layers, status, tax, and how deletion interacts with all of it.

Product types: Point in time vs. period of time

Every product has a type, and the type is the first choice you make when creating one.

Point in time

Products that are consumed at a specific moment, such as an API call or a generated document. The customer is charged per event.

Period of time

Products that are valid over a stretch of time, such as a seat held for a month. The customer is charged for access or capacity held across a window.
This split determines how the system prorates the product and recognizes it as revenue. You can prorate a seat added mid-month; you cannot prorate an API call, since it either occurred or did not.

Product subtypes: Measure usage within a type

Each product type supports a small set of product subtypes, and the one you choose determines how usage is measured for that product. Point in time products can be measured as:

Quantity

A count of discrete items, such as 5 report generations or 100 API calls.

Credits

A pool of credits or custom currency units, such as $100 in platform credits. Available through the API; the dashboard’s product subtype selector currently disables it.
Period of time products can be measured as:

Quantity

A specific amount of usage held over a period, such as 5 seats per month.

Feature

A service enabled or disabled for the period, such as priority support or white-labeling. Available through the API; the dashboard’s product subtype selector currently disables it.
Credits and Feature are each valid for exactly one product type; only Quantity works for both. This isn’t a soft default, it’s enforced at creation: picking Credits for a period of time product, or Feature for a point in time one, is rejected outright.

How pricing turns usage into a bill

After a product exists, you attach a pricing preset to it to define how usage becomes a billed amount. The system resolves this in layers: first the pricing model, then quantity strategy, then, if recurring, how usage is timed against the billing period. Pricing model determines how the system calculates the rate. Four are available from the dashboard: per unit, where every unit costs the same; percent, where the charge is a percentage of the metered amount rather than a flat rate per unit; volume, where the total quantity picks one rate for all units; and tiered, where usage is split across brackets and each portion is charged at its own rate. Package (billed in whole blocks) and step (one flat fee per quantity band) also exist and are selectable through the API; the dashboard’s pricing model selector doesn’t offer either yet.

Pricing models

Compare Zenskar’s pricing models, and see how each one applies to point in time and period of time products.
Separately, quantity can be metered (tracked from a meter) or fixed (a declared value set upfront). That choice governs where the number comes from, not when it’s billed. Quantity strategy governs the latter, and it applies either way, metered or fixed:

On demand

The system tracks and bills usage as it occurs.

Recurring

The system bills usage on a recurring schedule.
Selecting recurring introduces one more setting, partial period handling, since usage can start or stop partway through a billing period:

Prorate

The system charges only for the portion of the period used.

Charge full

The system charges the full amount regardless of when usage started.
On-demand usage has no partial period to prorate against. The system bills it at the moment it occurs, so this setting surfaces only when you select recurring. When usage is metered, the pricing preset stores only a reference to the meter, not the aggregation logic itself. The meter defines how usage is counted and where it comes from; the pricing preset just points to it, so changing how a meter aggregates usage takes effect for every pricing preset that references it, without editing the preset.

A product can carry more than one pricing preset

A product is not limited to a single pricing preset:
  • More than one preset: after a product exists, you can attach additional presets to it, each representing a different way to price that product, for example a flat per-unit rate alongside one or more volume-tiered rates with different tier bands.
  • Per-preset overrides: each pricing preset can carry its own alias (a short, human-friendly lookup name distinct from the product’s own name) and its own unit label, overriding the product’s default unit for that preset specifically. Both are optional; a preset with no alias or unit override falls back to the product’s own values.
  • Default is tracked per currency, not once per product: you can mark one preset as default for USD and a separate preset as default for EUR at the same time. When you add the product to a contract, the system uses whichever preset is default for the contract’s currency, unless you explicitly select a different one for that contract. The first preset created for a product in a given currency becomes that currency’s default automatically.
This is what allows the same product to carry different pricing across contracts and currencies without duplicating the product itself: the presets already exist side by side, and each contract points to whichever one applies.

Type is locked once pricing exists

The dashboard’s creation flow requires a pricing preset before you can save a product, so in practice type and pricing are set together in the same flow. The API is more permissive: a product can be created with no pricing attached at all, since pricing is added through a separate call. In that case, type stays open until the first pricing preset is attached. Once any pricing preset exists, type can’t change until every pricing preset is removed. In practice this is permanent, since pricing presets currently can’t be removed once created. This restriction is deliberate. Proration and revenue recognition both depend on the type. Allowing the type to change while pricing exists would risk a mismatch between what the pricing assumes and what the product actually is. Zenskar blocks the change instead.

Product status

A product moves through three statuses over its life:

Active

The default status when a product is created. Marks a product as current.

Inactive

Marks a product as not intended for new business. Existing contracts that already reference it continue to work.

Archived

End of life for a product. Cannot be set when a product is first created.
You cannot set a product to inactive while any contract still references it, active, expired, or otherwise, as long as the reference hasn’t been removed. Archiving is intended to be permanent: there is no supported way to move a product back to active or inactive once it’s archived. Status marks where a product stands in its lifecycle; it does not affect whether the product still exists or whether past invoices remain valid. Changing a product’s status and deleting a product are both currently API-only. The dashboard doesn’t yet have controls for either; the product’s detail page only displays its current status.

Contracts and invoices reference products; they do not copy them

Contracts and invoices reference a product by ID rather than copying its fields onto themselves. As a result, editing a product’s name, description, tax category, SKU, or unit label propagates automatically to everything that references it, with one exception at the finalized-invoice boundary: An already-created pricing preset is a separate exception to this, unrelated to finalization: pricing cannot currently be edited or removed once created, only added to, so there is nothing for a later product edit to propagate into. A pricing preset added to a contract’s line item from within the contract itself has its currency locked to the contract’s own currency; a preset created directly on the product isn’t constrained this way.

Tax identity belongs to the product, not the contract

Each product carries a tax category, since the product is the SKU that determines the applicable tax category. This is a property of what is being sold, not of the buyer or the contract. Without a tax category, the product is treated as non-taxable or handled outside Zenskar. The product supplies only half of the tax calculation. The pricing on top of it specifies the tax behavior: today that’s fixed to tax-exclusive, meaning the quoted price excludes tax and tax is added on top. A tax-inclusive option exists in the underlying schema but isn’t wired through the invoice tax pipeline yet, so it’s rejected if set and isn’t offered as a choice in the dashboard. Zenskar combines the product’s tax category and the pricing’s tax behavior to determine the actual tax rate and value at invoicing time. The rates themselves reside at the organization level (via Avalara, Anrok, or managed manually), so the product only points to a category, and Zenskar performs the lookup.

Avalara AvaTax

Set up Avalara as the tax rate source for an organization.

Anrok

Set up Anrok as the tax rate source for an organization.
If your organization uses Anrok for tax, creating or updating a product whose tax category maps to an Anrok category also keeps Anrok’s own product catalog in sync automatically; there’s nothing separate to configure for that.

Deletion is permanent, but contract references hold it back

You cannot delete a product while any contract still references it; you must remove it from every contract first. Once deleted, its pricing presets are soft-deleted along with it. Already-finalized invoices remain unaffected in either case, since their historical data does not depend on the continued existence of the product record.