> ## 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.

# Editing prices

> How edits to a price, its entitlement template, and related fees propagate to existing subscribers

When you update a price, an attached entitlement template, or a linked fee, the change affects existing subscribers in one of four ways:

1. **Propagated** — the new value applies to existing subscribers from the next billing period onward.
2. **Frozen** — the current uninvoiced period keeps the old value; the new value applies starting next period.
3. **Snapshotted** — the value was captured at subscription activation and is not rewritten; the new value affects only new subscribers.
4. **Blocked** — the update is rejected when the price has active or pending-payment subscribers.

This page documents which fields fall into each category and the recommended workflow when you need to make a blocked change.

<Info>
  Propagation only applies to Standard Billing (`billingVersion: 1`). Legacy
  Billing uses a different flow — see [Billing Versions](/platform/billing/billing-versions).
</Info>

## 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                                                                           |

Already-invoiced line items are never modified — invoices are immutable once issued.

## Entitlement template propagation

When a price carries an `entitlementTemplate`, 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`

These are blocked because mid-cycle propagation would surprise customers: cadence or anchor shifts would reissue grants at unexpected times, and flipping soft/hard limit would silently change overage behavior mid-period.

The API rejects the request with a `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

1. **Clone the price** with the new shape (`POST /v0/prices`).
2. **Reference the new price** from a new plan, or update an existing plan's price list to include it.
3. **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).

This pattern keeps existing subscribers on the old configuration until they migrate explicitly, avoiding mid-cycle surprises.

<Note>
  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.
</Note>

### 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.

If you need a snapshotted change to take effect on existing subscribers, follow the same clone-and-migrate workflow as for blocked changes.

## Direct and purchase grants

Grants created via `POST /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.

<Warning>
  When a subscription is terminated, all metered-feature grants attached to it
  are voided — including direct and purchase grants. If you support prepaid
  credit packs, surface this in your cancellation flow so customers are not
  surprised by lost balances.
</Warning>

## Next steps

* [Prices](/platform/pricing/prices) — pricing models and payment terms
* [Features and Entitlements](/platform/pricing/features) — entitlement template reference
* [Metered Entitlements](/platform/billing/metered-entitlements) — how metered grants are consumed
* [Grants](/platform/billing/grants) — direct and purchase grant APIs
