Summary

✍️ We know that a renegotiated contract is rarely one edit, and until now every edit was live the moment you saved it. This release is about getting a change reviewed before it bills: pricing plan schedules gain an explicit draft status with an approval gate, pricing categories can finally be reordered on a plan version, and workflow trigger conditions get a proper editor in Desk with nested AND/OR groups. On the invoicing side, tax summaries are split per rate, wallet grants are reversed when an invoice is voided, and an invoice containing a deduction can reach PAID again. A reactivate action for deprecated meters and clearer custom field ownership round out the release.

Pricing

Draft status on pricing plan schedules A pricing plan schedule now carries an explicit status, either DRAFT or ACTIVE, defaulting to ACTIVE so existing integrations are unaffected. A draft schedule can be prepared and reviewed before it takes effect, which is what an approval flow needs; initializing a subscription with status ACTIVE is rejected when its earliest schedule is still a draft, so a subscription cannot go live against a schedule nobody signed off on. The read-only approval_status of the associated approval request is exposed on the schedule alongside it. Draft schedules covers the full flow, including the permissions below.

A read-only is_current was added at the same time, combining the schedule’s date window with its status so you can tell what a customer is on today without evaluating both yourself. Drafts are promoted through POST /v1/pricing-plan-schedules/{id}/activate for one schedule, or POST /v1/pricing-plan-schedules/activate?pricing_plan_subscription_id=... to activate every draft schedule of a subscription in one all-or-nothing batch, so a multi-schedule change goes live together or not at all. Two permissions govern this: PRICING_PLAN_SCHEDULE.STATUS.UPDATE to activate a draft, and PRICING_PLAN_SCHEDULE.WRITE_ACTIVE to create, copy or migrate a schedule that is not a draft. A user who only holds the first can prepare changes but not put them live. Quote schedules keep their own quote permissions and are unaffected.

Reorder pricing categories on a plan version display_order on a pricing category is now honoured. Previously the order of categories on a pricing plan version always followed the order of the product categories in the catalog, and patching display_order through PATCH /v1/pricing-plan-versions/{id} had no effect, so the only way to change how a plan reads was to reorder the catalog itself. Ordering is validated as a complete permutation: set it on all categories or on none, each value unique, and the values covering 1 through the number of categories without gaps. Desk exposes the reordering on the pricing plan version screen.

Invoices

Tax summaries are split per rate The tax summary key now combines the tax category with the rate instead of the category alone, so an invoice that applies more than one rate within the same category (a mixed-rate AvaTax result, for example) produces one summary line per rate rather than collapsing them into a single line with a blended base. Invoice groups are grouped the same way as the periods and the invoice itself, so the totals reconcile at every level. The Canadian tax engine keys on the combined rate too; it resolves one rate set per customer, so nothing splits there today, but the behaviour is now consistent across engines. Cost prediction follows the same grouping.

Fixes

bug-fix
  • An invoice that contains a deduction can reach PAID again. The payment status compared the paid amount against the invoice total before deductions, but the deducted part is settled through the deduction and is never invoiced, so no payment could ever cover it and the status stayed PARTIALLY_PAID forever. It now compares against the open amount, which is what “paid” means for such an invoice.
  • Wallet grants that came from an invoice are reversed when that invoice is voided, so voiding a top-up no longer leaves the customer with credits they did not pay for.
  • Credit notes and one-off invoices are excluded from reprocessing. Reprocessing only regenerates standard invoices, which is the only kind whose lines are derived from usage.
  • The per-seat unit price is shown in the price column of an invoice line for per-seat pricing. A line showing a quantity of 30 seats now also states the price per seat, matching how the subscription presents the same pricing.

Workflows

Trigger conditions in Desk The conditions tree on a workflow trigger, added to the API in a previous release, now has an editor in Desk. You build comparisons on the fields the trigger exposes, with the comparators allowed for each field type, and combine them into nested AND/OR groups. The recursive tree editor is shared with the meter condition editor, so workflow conditions are no longer limited to a flat list of ANDs while the API accepted nested groups: a rule such as “only for credit notes above $500, or for any invoice of a customer in this segment” can be expressed in the UI.

Quotes

Fixes

bug-fix
  • An upgrade quote with a start date after the end of the original subscription’s schedule is now rejected outright. The request returned an INVALID_FIELD error but created the quote and its version anyway, leaving an invalid quote behind.

Meters and events

Reactivate a deprecated meter A meter in DEPRECATED status can be activated again from Desk. The transition was already allowed by the API, but the Activate action was missing from the status menu, so a deprecated meter could only be archived, and archiving is the one step in the resource lifecycle you cannot walk back. Deprecating a meter you still need is a common mistake when tidying up a catalog: the meter keeps matching events but is hidden from new configuration, and the fix is now a single action rather than rebuilding the meter and re-pointing every product item at it.

Reporting

Request a usage report from the invoice The “Request usage report” action stays available on an invoice that already has a usage report. The button previously disappeared as soon as one report existed, so requesting a fresh one meant going to the Reports tab and pasting the invoice id. That is the wrong way round for the common case: a usage report is most often re-requested precisely because an earlier one is now stale, after usage was reprocessed or a dispute made the numbers worth re-checking. Support agents answering “can you send me the detail behind this line” can now do it from the invoice they are already looking at.

Integrations

Custom fields state which integration they belong to A custom field created for a system integration now exposes a read-only integration_type next to its integration_id and integration_reference, and the reference itself became read-only, so the link between a field and the integration that owns it cannot drift. Sandboxes seed the Adyen and email integrations with named custom fields (“Adyen Shopper Reference”, “Adyen Balance Account” and so on) under clearly named integrations, so it is obvious which fields are managed for you and should not be edited by hand.