Scheduled changes
A scheduled change is a typed, future-dated mutation queued against a billing entity. Use them whenever a change shouldn't apply immediately - a plan switch at renewal, a price increase with mandatory notice, a tax rate rolling over at year-end, a coordinated release across multiple entities.
Two ways to create one:
- Per-entity convenience endpoint -
POST /v1/{entity}/{id}/schedule- the right call when you're scheduling against a specific catalog entity. Available forproducts,plans,prices,promotions,tax-rules. The handler builds the rightchange_payloadshape for that entity from a typed body. - Generic endpoint -
POST /v1/scheduled-changes- for cases that don't fit a single entity (cross-entity dependencies, custom payloads, or admin tooling that wants the full struct surface).
Both paths produce the same ScheduledChange row and ride the same lifecycle.
Entity types
entity_type decides what the engine does at release time. Seven values:
PRICE · PRODUCT · PLAN · PROMOTION · TAX_RULE · COST · SUBSCRIPTION
For the catalog entities (PRICE / PRODUCT / PLAN / PROMOTION / TAX_RULE / COST), schedules typically publish a new version at the scheduled time - the entity's version timeline gets a new active row. For SUBSCRIPTION, schedules change the subscription's state directly (plan transition, quantity change, cancellation).
Lifecycle
Code
| Status | Meaning |
|---|---|
pending | Created, scheduled time is far enough out that no notification has fired |
upcoming | Notification window entered - the customer / operator has been told the change is coming |
releasing | Effective time reached, the engine is in the middle of applying it |
released | Successfully applied. Catalog entities now have a new active version; subscription state is changed |
stale | The underlying entity was modified after this change was scheduled - the change needs reconfirm before it can release |
rolled_back | A released change was reverted (terminal) |
cancelled | Removed before release (terminal) |
Webhooks: scheduled_change.created, scheduled_change.upcoming, scheduled_change.reconfirmed, scheduled_change.released, scheduled_change.rolled_back, scheduled_change.cancelled (see Webhook events).
Anatomy
| Field | Notes |
|---|---|
entity_type + entity_id | What's being changed |
change_type | Optional string tag - narrows what this scheduled change does within the entity (e.g. plan_transition vs quantity_change for subscriptions). The per-entity endpoints set it for you |
change_payload | Typed JSON body the release-time handler consumes. Per-entity endpoints generate it; generic POST takes it as json.RawMessage |
scheduled_at | When the change should release (ISO 8601, UTC) |
release_strategy | AUTOMATIC (default) - engine releases at scheduled_at. MANUAL - sits in upcoming until an operator calls POST /release. CANARY - phased rollout (used by bulk-migration flows where the first 1% release, get observed, then the rest follow) |
notification_config | Optional config blob - recipient list + lead-time per channel (email, webhook). Org default applies when null |
rollback_window | Optional duration string (e.g. "72h") - how long after release the change can be rolled back |
depends_on_change_id | Another scheduled change that must release before this one. Used for ordered multi-entity rollouts |
entity_version_at_schedule | The entity's version when the change was scheduled. The engine compares against the live version at release time - if they don't match, the change goes stale |
previous_state | Read-only snapshot of the pre-change state, captured at release time. Powers rollback |
Scheduling per entity
For most cases, use the per-entity endpoint - the typed body is much smaller than the generic one.
Code
Available per-entity endpoints:
Code
Each one creates a ScheduledChange and returns it. Per-entity-version cancellation:
Code
These act on the version timeline of a specific entity rather than going through the generic scheduled-change ID, which is friendlier for catalog tooling.
Generic create
For one-off changes (subscriptions, custom payloads, cross-entity dependencies):
Code
Reconfirmation: the stale state
When the underlying entity is mutated after a change was scheduled (someone publishes a new plan version, tax rate, or price under it), the engine flips the change to stale. The release pipeline refuses to apply stale changes - you have to either:
POST /v1/scheduled-changes/{id}/reconfirm- re-validates against the current entity state and moves back topending(orcancelledwith a reason if the change is no longer valid).- Cancel the change and re-schedule against the new state.
Reconfirm exists per-entity-version too (POST /{entity}/{id}/versions/{vid}/reconfirm) for the catalog-tool ergonomics. Either form does the same thing.
Release & rollback
AUTOMATIC schedules release themselves at scheduled_at. For MANUAL (or to release early):
Code
Once released, the rollback window starts:
Code
Rollback restores the entity to previous_state going forward - it does not retroactively un-bill. If the released change had already produced invoice lines, a rollback typically issues a credit note for the period billed under the released change. Rollbacks fire scheduled_change.rolled_back.
Cancellation
Code
Valid only before release (pending, upcoming, or stale). Terminal released / rolled_back / cancelled reject the call. After release, use rollback instead.
Dependencies
depends_on_change_id makes one scheduled change wait on another's released status before it can release itself. Used for ordered rollouts - e.g. publish the new tax rule first, then transition all subscriptions onto a plan that depends on it. The dependent change shows pending until its dependency releases.
Endpoints
All Scheduled Changes endpoints - generic CRUD + release / rollback / reconfirm. Per-entity scheduling is documented under each entity's own tag (Plans, Prices, Promotions, Products, Tax Rules).
Related
- Plans -
POST /plans/{id}/scheduleand themigrate-subscribersbulk path - Promotions -
POST /promotions/{id}/schedulefor promotion edits - Taxes -
POST /tax-rules/{id}/schedulefor rate rollovers - Subscriptions - schedule a
transition-planfor a future date - Webhooks → events - full event catalog