[API GUIDE] Upgrade a Subscription Immediately
Overview
This guide shows you how to implement the Update Subscription Item endpoint to upgrade a subscription with immediate effect.
Use case
Upgrade the annual subscription plan from limited (Premium) to unlimited (Platinum).
- A customer signs up for the Cloudify Premium plan for $900.00 per year, which includes 100GB of storage.
- The customer decides to upgrade to Cloudify Platinum plan with unlimited storage and visits the upgrade page.
- The page uses the Update Subscription Item endpoint to show a pro-rated price for upgrading for the rest of the current billing period.
- After reviewing the price, the customer confirms the upgrade. Cloudify uses the Update Subscription Item endpoint again to apply the upgrade immediately.
- Cleverbridge charges the customer the pro-rated upgrade amount for the remaining time in the current billing cycle.
Result
At the next renewal, Cleverbridge automatically bills the full annual price for the Premium plan.
Implement the Update Subscription Item endpoint
In this case, the Update Subscription Item endpoint is called twice, using different parameters.
Before you start
Make sure that:
- The subscription has the status
Active. - The product to which the customer wants to upgrade has been set up in the Cleverbridge platform.
- Both products have the same billing interval.
- Using this API endpoint to change the billing interval of a subscription is only supported for single-item subscriptions (which is the most common type of subscription), and only effective at the time of the next billing date. Otherwise, when one subscription item is replaced with another, the original and the replacement items must have the same currency and billing interval.
- Changes made by this function, including the price and/or quantity, apply to current and all future billing events unless changed subsequently.
- When you add a subscription item, a history of revisions is created automatically. It is important to confirm that the current version receives the update.
For more information on which API endpoint to use, see Guidelines for When to Use UpdateSubscriptionItem vs. UpdateSubscriptionItemPrice.
ImportantGet the customer's consent before making changes to a subscription.
To avoid chargebacks and customer inquiries, it is also essential that you coordinate all price increases with Client Experience.
In the European Economic Area (EEA), Strong Customer Authentication (SCA) is required for recurring electronic payments when the amount changes. This means that some of your customers will have to authenticate their payment, which in turn might impact the renewal success rate.
For more information, see Best Practices: Obtain Customer Consent.
Step 1: Preview of pro-rated billing amount
In the first call:
If the API call is formatted as described below, it will behave as the following:
- Calculate the pro-rated price to be billed if the upgrade is made.
- Return the pro-rated billing amount in the
AlignmentCustomerGrossPriceparameter of the API response (so that it can be provided to the customer). - Not change any data in the Cleverbridge system.
Parameters
Parameter | Type | Required | Example | Notes |
|---|---|---|---|---|
AlignmentSettings | obj | Yes |
| The subscription is **NOT **changed. |
ProductId | int | Yes | 293104 | The product ID for the premium plan product (not the current basic plan product being replaced). |
Quantity | int | Yes | 1 | Total number of items after the update. |
RunningNumber | int | Yes | 1 | Running number of the item in the subscription. |
SubscriptionId | str | Yes | S68448978 | The unique identifier of the subscription. |
UpdateAction | str | Yes | 0 | Used for reporting only. It does not affect the subscription. |
JSON body
{
"ProductId": 293104,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 0,
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": true
}
}Request
curl --location 'https://rest.cleverbridge.com/subscription/updatesubscriptionitem'
--header 'Content-Type: application/json'
--header 'Accept: application/json'
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS'
--data '{
"ProductId": 293104,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 0,
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": true
}
}'import http.client
import json
conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
"ProductId": 293104,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 0,
"AlignmentSettings": {
"AlignToCurrentInterval": True,
"GetCustomerPricePreviewOnly": True
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("POST", "/subscription/updatesubscriptionitem", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))var https = require('follow-redirects').https;
var fs = require('fs');
var options = {
'method': 'POST',
'hostname': 'rest.cleverbridge.com',
'path': '/subscription/updatesubscriptionitem',
'headers': {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS',
'maxRedirects': 20
};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
res.on("error", function (error) {
console.error(error);
});
});
var postData = JSON.stringify({
"ProductId": 293104,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 0,
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": true
}
});
req.write(postData);
req.end();Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://rest.cleverbridge.com/subscription/updatesubscriptionitem")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
.body("{\n \"ProductId\": 293104,\n \"RunningNumber\": 1,\n \"Quantity\": 1,\n \"SubscriptionId\": \"S68448978\",\n \"UpdateAction\": 0,\n \"AlignmentSettings\": {\n \"AlignToCurrentInterval\": true,\n \"GetCustomerPricePreviewOnly\": true\n }\n}")
.asString();
Response
{
"AlignmentCustomerGrossPrice": 0.0,
"AlignmentCustomerNetPrice": 0.0,
"AlignmentCustomerVatPrice": 0.0,
"NextBillingCustomerGrossPrice": 900.0,
"NextBillingCustomerNetPrice": 756.3,
"NextBillingCustomerVatPrice": 143.7,
"NextRenewalCustomerGrossPrice": 900.0,
"NextRenewalCustomerNetPrice": 756.3,
"NextRenewalCustomerVatPrice": 143.7,
"PriceCurrencyId": "USD",
"ResultMessage": "OK"
}Step 2: Upgrade by replacing the basic plan with the premium plan
In the second call:
If the API call is formatted as described below, it will update the customer's subscription data in the Cleverbridge platform.
Parameters
Parameter | Type | Required | Example | Notes |
|---|---|---|---|---|
AlignmentSettings | obj | No |
| The subscription is changed as requested in the API call. |
ProductId | int | Yes | 294514 | The product ID for the premium plan product (not the current basic plan product being replaced). |
RunningNumber | int | Yes | 1 | Running number of the item in the subscription. |
Quantity | int | Yes | 1 | Total number of items after the update. |
SubscriptionId | str | Yes |
| The unique identifier of the primary subscription. |
UpdateAction | str | No | 1 | The value set does not affect transaction processing. |
NoteThe
UpdateActionparameter is currently used for documentation and tracking only. The value set does not affect transaction processing.The supported values are as follows:
- For upgrades, set the parameter to
upgrade(or1for JSON)- For downgrades, set the parameter to
downgrade, (or2for JSON)- For all other changes, set the parameter to
update(or0for JSON)
JSON body
{
"ProductId": 294514,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 1,
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": false
}
}Request
curl --location 'https://rest.cleverbridge.com/subscription/updatesubscriptionitem'
--header 'Content-Type: application/json'
--header 'Accept: application/json'
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS'
--data '{
"ProductId": 294514,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 1,
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": false
}
}'import http.client
import json
conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
"ProductId": 294514,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 1,
"AlignmentSettings": {
"AlignToCurrentInterval": True,
"GetCustomerPricePreviewOnly": False
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("POST", "/subscription/updatesubscriptionitem", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))var https = require('follow-redirects').https;
var fs = require('fs');
var options = {
'method': 'POST',
'hostname': 'rest.cleverbridge.com',
'path': '/subscription/updatesubscriptionitem',
'headers': {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
},
'maxRedirects': 20
};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
res.on("error", function (error) {
console.error(error);
});
});
var postData = JSON.stringify({
"ProductId": 294514,
"RunningNumber": 1,
"Quantity": 1,
"SubscriptionId": "S68448978",
"UpdateAction": 1,
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": false
}
});
req.write(postData);
req.end();Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://rest.cleverbridge.com/subscription/updatesubscriptionitem")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
.body("{\n \"ProductId\": 294514,\n \"RunningNumber\": 1,\n \"Quantity\": 1,\n \"SubscriptionId\": \"S68448978\",\n \"UpdateAction\": 1,\n \"AlignmentSettings\": {\n \"AlignToCurrentInterval\": true,\n \"GetCustomerPricePreviewOnly\": false\n }\n}")
.asString();Response
{
"AlignmentCustomerGrossPrice": 861.38,
"AlignmentCustomerNetPrice": 723.85,
"AlignmentCustomerVatPrice": 137.53,
"NextBillingCustomerGrossPrice": 150.0,
"NextBillingCustomerNetPrice": 126.05,
"NextBillingCustomerVatPrice": 23.95,
"NextRenewalCustomerGrossPrice": 150.0,
"NextRenewalCustomerNetPrice": 126.05,
"NextRenewalCustomerVatPrice": 23.95,
"PriceCurrencyId": "USD",
"ResultMessage": "OK"
}Diagram
flowchart LR
classDef mainColor fill:#ffffff,color:#555555,stroke:#96C34B,stroke-width:2px;
A([" <br/><b>Price Preview</b><br/><i>Update Subscription Item</i> endpoint used to calculate pro-rated price <br/> "]):::mainColor
--> B([" <br/><b>Upgrade to Premium Plan</b><br/><i>Update Subscription Item</i> endpoint used to complete the upgrade <br/> "]):::mainColor
--> C([" <br/><b>Billing</b><br/>Cleverbridge automatically bills the customer the full renewal price <br/> "]):::mainColorUpdated about 4 hours ago