[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).

  1. A customer signs up for the Cloudify Premium plan for $900.00 per year, which includes 100GB of storage.
  2. The customer decides to upgrade to Cloudify Platinum plan with unlimited storage and visits the upgrade page.
  3. The page uses the Update Subscription Item endpoint to show a pro-rated price for upgrading for the rest of the current billing period.
  4. After reviewing the price, the customer confirms the upgrade. Cloudify uses the Update Subscription Item endpoint again to apply the upgrade immediately.
  5. 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.

🚧

Important

Get 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 AlignmentCustomerGrossPrice parameter 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

AlignToCurrentInterval: true
GetCustomerPricePreviewOnly: true

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

AlignToCurrentInterval: true
GetCustomerPricePreviewOnly: false

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

S68448978

The unique identifier of the primary subscription.

UpdateAction

str

No

1

The value set does not affect transaction processing.
See the note below.


📘

Note

The UpdateAction parameter 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 (or 1 for JSON)
  • For downgrades, set the parameter to downgrade, (or 2 for JSON)
  • For all other changes, set the parameter to update (or 0 for 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(["&nbsp;&nbsp;<br/><b>Price Preview</b><br/><i>Update Subscription Item</i> endpoint used to calculate  pro-rated price&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> B(["&nbsp;&nbsp;<br/><b>Upgrade to Premium Plan</b><br/><i>Update Subscription Item</i> endpoint used to complete the upgrade&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> C(["&nbsp;&nbsp;<br/><b>Billing</b><br/>Cleverbridge automatically bills the customer the full renewal price&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor