This recipe raises Pro from $20 to $25 a month and its export allowance from 5,000 to 10,000. When you are done:
- new subscribers get the new price and allowance;
- the customers already on Pro keep paying $20 for 5,000 exports, until they change plan themselves;
- your backend and frontend have not changed, and nothing was deployed.
This works because your code never names a plan or a price. Your backend rules on capability keys, and the frontend components read the catalog from your application's region at runtime.
How it works
A plan's price, currency, billing interval and entitlement rules live on its numbered versions, and a published version never changes. A subscription points at the version it was taken on. Changing the price is therefore publishing a new version: the catalog offers the latest published version of each plan, and every existing subscription stays where it is. Plan versions covers the model in full.
1. Create the next version
In the operator console, under Products & Plans, open Pro and choose Create Next Draft. Through the Management API:
POST /mgt/v1/projects/{projectId}/plans/{planId}/versions
Authorization: Bearer <operator session token>The draft is numbered after the latest version and copies its price, currency, billing interval, overage discount and rules. Here it is version 2, priced $20 with an allowance of 5,000, until you change it.
2. Change the price and the allowance
PATCH /mgt/v1/projects/{projectId}/plans/{planId}/versions/2
Authorization: Bearer <operator session token>
Content-Type: application/json
{ "price_amount": 25 }PUT /mgt/v1/projects/{projectId}/plans/{planId}/versions/2/rules
Authorization: Bearer <operator session token>
Content-Type: application/json
{ "rules": [{ "capability_id": "<report_exports>", "allowance": 10000, "reset_interval": "MONTHLY" }] }PUT …/rules replaces all the rules of the draft, so list every capability the version grants, not only the one you change.
In the console, choose Save Draft after changing the rules and before Publish Version; a rule added and published without saving is left out of the published version.
3. Publish
POST /mgt/v1/projects/{projectId}/plans/{planId}/versions/2/publish
Authorization: Bearer <operator session token>From this moment the version is frozen. Changing it is refused with VERSION_IMMUTABLE, as is changing version 1; publishing it again is refused with VERSION_ALREADY_PUBLISHED.
What happens on Stripe depends on the application's payment connection:
| Payment connection | When you publish version 2 |
|---|---|
| Connected | ShipRev creates a new product and a new recurring price of $25 on your Stripe account first, then freezes the version. If Stripe refuses, the version stays a draft; fix the cause and publish again |
| Not connected yet | The version is frozen at once and waits to be synced; its external_price_ref is null. It is synced when you connect an account. Until then checkout on it is refused with PAYMENT_PROVIDER_NOT_CONFIGURED |
The price created for version 1 stays on Stripe as it was, and existing Stripe subscriptions keep renewing on it.
What everyone sees afterwards
| Who | Gets |
|---|---|
| A signed-in end user without a subscription | GET /public/v1/catalog/plans lists Pro with latest_version 2: $25 and 10,000 exports. PricingTable shows the same, and checkout uses version 2 |
| An organization already on Pro | Its subscription still points at version 1. Rulings keep limit at 5,000 and renewals stay at $20. Its entitlements are not rebuilt when you publish |
| Your backend | Nothing to change: it still rules on report_exports. New subscribers on version 2 are ruled against 10,000 |
Moving existing subscribers
An existing subscriber moves to version 2 only by changing plan themselves. PricingTable lists Pro with its latest version, so a subscriber on version 1 sees Pro as a plan they can switch to, and the switch is charged like any plan change; see Change plan. Moving existing subscribers to a new version in bulk is not available.
A subscription that was activated by hand, rather than through Stripe checkout, cannot be changed by the end user: the change is refused with PLAN_CHANGE_NOT_ALLOWED. You move it with POST /mgt/v1/projects/{projectId}/subscriptions/{subscriptionId}/change-plan and the new plan_version_id.
Try it
- Activate a test organization A on Pro version 1, through checkout in Stripe's test mode or by hand with
POST /mgt/v1/projects/{projectId}/subscriptions/activateand{ "organization_id": "<A>", "plan_version_id": "<version 1>" }. - Run steps 1 to 3.
- Rule for A in your backend:
limitis still 5,000. ReadGET /public/v1/subscriptionsas A:plan_versionis still 1. - Activate a second test organization B on the latest version. Its rulings show
limit10,000.