When you update a price, an attached entitlement template, or a linked fee, the change affects existing subscribers in one of four ways:Documentation Index
Fetch the complete documentation index at: https://docs.paygentic.io/llms.txt
Use this file to discover all available pages before exploring further.
- Propagated — the new value applies to existing subscribers from the next billing period onward.
- Frozen — the current uninvoiced period keeps the old value; the new value applies starting next period.
- Snapshotted — the value was captured at subscription activation and is not rewritten; the new value affects only new subscribers.
- Blocked — the update is rejected when the price has active or pending-payment subscribers.
Propagation only applies to Standard Billing (
billingVersion: 1). Legacy
Billing uses a different flow — see Billing Versions.Price-level fields
Editing a price (PATCH /v0/prices/{id}) rewrites the underlying record. At the next line-item sync, future-period line items are regenerated with the new values. The current uninvoiced period is frozen: existing line items keep their old unitPrice, displayName, and other captured values so a mid-cycle edit does not retroactively change what the customer is being billed.
| Field | Edit allowed on price with active subs? | Effect on existing subs |
|---|---|---|
properties.unitPrice (and other model-specific properties) | Yes | Frozen for current uninvoiced period; new value applies from next period |
model (standard, dynamic, volume, percentage) | Yes | Frozen for current uninvoiced period; new value applies from next period |
paymentTerm (in_advance ↔ in_arrears) | Yes | Current-period line items are replaced with the new direction (freeze is bypassed because the billing direction shifts) |
invoiceDisplayName | Yes | Frozen for current uninvoiced period; new value applies from next period |
billableMetricId | Yes | Future-period line items use the new metric; current uninvoiced items keep the old one |
grantDiscountEnabled | Yes | Applies to future grant-discount calculations |
Entitlement template propagation
When a price carries anentitlementTemplate, edits to the template fields propagate to existing subscribers’ grants through a separate path (grant reinitialization), with stricter rules than price-level fields.
| Field | Edit allowed on price with active subs? | Propagates to existing subs? |
|---|---|---|
issueAfterReset (any value, including 0 ↔ N and undefined ↔ N) | Yes | Yes — at next line-item sync |
resetMaxRollover | Yes | Yes — at next line-item sync |
resetMinRollover | Yes | Yes — at next line-item sync |
expiration | Yes | Yes — at next line-item sync |
preserveOverageAtReset | Yes | No — snapshotted at activation |
issueAfterResetPriority | Yes | No — only rewritten as a side effect when another field above drifts |
isSoftLimit | No — blocked | n/a — change rejected |
usagePeriod presence (recurring ↔ one-time) | No — blocked | n/a — change rejected |
usagePeriod.interval | No — blocked | n/a — change rejected |
usagePeriod.anchor | No — blocked | n/a — change rejected |
When propagation happens
Propagated template fields apply at the next line-item sync for each subscription, which typically aligns with the next period boundary. The change is not instant. Internally, grant reinitialization runs as a post-sync hook after new metered line items are created. A drift detector compares the current template against the subscription’s active recurring grant; when a propagated field differs, the grant is reinitialised at the new period boundary. If a subscriber is mid-period when you edit the template, the current period continues with the old grant values. The new values take effect from the next period.Blocked template changes
updatePrice rejects the following template changes when the price has active or pending-payment subscribers:
- Toggling
isSoftLimit - Adding or removing
usagePeriod(switching between recurring and one-time grants) - Changing
usagePeriod.interval - Changing
usagePeriod.anchor
400 Bad Request describing the offending field. The diff is per feature, so edits to other (non-blocked) fields in the same call still go through.
Recommended workflow for blocked changes
- Clone the price with the new shape (
POST /v0/prices). - Reference the new price from a new plan, or update an existing plan’s price list to include it.
- Migrate subscriptions off the old plan onto the new plan at the appropriate cycle boundary (terminate on the old plan, recreate on the new plan).
We are working on first-class plan transitions — upgrades, downgrades, and
cross-grades — that will handle subscription migration automatically with
proration and grant carry-over. The clone-and-migrate workflow above is the
recommended path until those land.
Snapshotted template fields
Some template fields are captured on the entitlement at activation and never rewritten:preserveOverageAtReset— captured when the entitlement is provisioned. Editing it on the template affects new subscribers only.issueAfterResetPriority— does not itself trigger reinitialization. It is rewritten only as a side effect when another propagated field drifts.
Direct and purchase grants
Grants created viaPOST /v1/entitlements/{id}/grants (direct grants) or POST /v1/entitlements/{id}/grants/purchase (purchase grants) are independent of the entitlement template. Editing the template on a price never modifies these grants.
Next steps
- Prices — pricing models and payment terms
- Features and Entitlements — entitlement template reference
- Metered Entitlements — how metered grants are consumed
- Grants — direct and purchase grant APIs