draft, edited freely, and then published to take effect on its effective date. Only one published version is in effect at a time (current_version_id); future ones queue as pending_changes; past ones remain as an immutable record of what the customer was billed for and when. Understand this model before making any mid-term change: Amendments describes what you change, Proration describes what it costs, and this page describes the mechanism both rely on. See How Alguna Works for the object graph.
What a version holds
Contract dates, renewal terms, billing flags and subscription-level discount are not versioned; they sit on the subscription and change through
PATCH /subscriptions/{id}.
Version states
There are exactly two:
Where a version sits in time is derived from its dates, not from a separate state: a published version whose
start_date has passed and whose end_date is null or in the future is the current one; a published version with a future start_date is pending and appears in the subscription’s pending_changes; a published version with a past end_date is historical.
Draft subscriptions work the same way: a
draft subscription holds one or more versions that publish when the subscription is activated. Multiple versions on a draft are how ramped deals are set up; see Ramps and phases.Reading versions
404 from /versions/current means the subscription has no published version in effect yet (for example, a draft subscription).
Creating versions
There are two ways to produce a new version. Both end with apublished version and a subscription.version.updated webhook.
Delta: describe the change
POST /subscriptions/{id}/changes takes add, remove and update arrays plus an effective timing, computes the new version from the current one, and publishes it (or leaves it as a draft with draft: true). This is the path for almost every mid-term change and is covered in Amendments.
Snapshot: supply the whole item set
POST /subscriptions/{id}/versions takes a complete items array (every item with a full price definition), an optional entitlements array, an effective_at date and a description. Pass draft: true to stage it as a draft you can iterate on and publish later; without it the version is published as soon as it is created.
Working with a draft
On publish, a version whose
effective_at is today or in the past becomes current immediately; one with a future effective_at becomes pending until that date. Published versions cannot be deleted or edited; supersede them with a newer version instead.
Effective dates
An effective date is either a specificYYYY-MM-DD (or RFC 3339 timestamp) or, on the changes endpoint, a keyword:
Which dates are valid depends on the billing schedule.
GET /subscriptions/{id}/billing-dates returns the current cycle, the on-cycle dates, the range valid for mid-cycle changes, the contract end date and the next renewal date; use it to drive date pickers.
In the dashboard the same choice appears as From start of a billing cycle versus Mid-cycle when saving an edit to an active subscription.
Subscriptions that have not started yet
A subscription sold now but starting later — next quarter, next fiscal year — needs care, becauseimmediate means now, which is before the subscription begins. Adding a price with effective: immediate on a future-dated subscription puts the change earlier than the subscription’s own start date, which is not what you want.
Which path to take depends on whether the subscription has been activated:
-
Still a
draftsubscription. Its versions are drafts too and have no billing effect, so add the item to the draft version and publish. Nothing else is needed. -
Activated, with a future start date. The item set for the opening period lives in the published version whose
start_dateis the subscription’s start. To have the new price apply from day one, replace that version: create a version witheffective_atset to the subscription’s start date and a completeitemsarray including the new price. A published version already sits at exactly that date, so the API answers409 Conflictnaming it —a published version (…) already exists at …; delete it first then retry. That is the expected response, not a failure: delete that version and repeat the create. Deleting a scheduled version is safe — it has not billed anything. -
Adding the price from a later date instead. Use
POST /subscriptions/{id}/changeswitheffectiveset to that explicit date rather than a keyword. The result is a second version that takes over on the date you named, leaving the opening version intact.
Ramps and phases
A ramped contract (year-1 pilot pricing, year-2 full pricing, a 5% uplift in year 3) is a subscription with several versions scheduled up front, each with its ownstart_date and pricing:
Set them up in the dashboard by adding a phase per period on the subscription or quote before activation, or via the API by creating and publishing one version per phase with the appropriate
effective_at. Each future version shows in pending_changes until its date arrives. The customer signs once for the whole schedule when the deal goes through a quote.
For a uniform annual uplift, price_escalation on the subscription (a percentage every interval_months, optionally applied to metered unit rates too) is simpler than hand-building phases.