Combine an Immediate Product Upgrade with an Early Renewal


Overview

This guide shows you how to implement the Update Subscription Item endpoint to allow a customer to upgrade from basic to premium and renew a subscription effective immediately.

Use case

  1. The customer decides to switch from the monthly Cloudify Bronze plan to the monthly Gold plan before the end of the subscription interval.
  2. The customer confirms the purchase in the Self-Service area by clicking a Buy Now button. The Get Subscription endpoint is used to display the current price.
  3. Upgrade Confirmation: the Update Subscription Item endpoint is used to upgrade and renew the customer's subscription.

Result

The next billing interval starts immediately, and the customer is charged the full renewal price.
The unused time remaining in the current billing interval is carried over and added to the new billing interval.

Implement API workflow

Before you start

Make sure that:

  • The subscription has the status Active.

  • The current billing interval has started.

  • The renewal is not combined with an alignment of the subscription.

  • The product to which the customer wants to upgrade has been configured in the Cleverbridge platform.


Additional considerations

  • 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 takes effect at the next billing date.

  • Changes made by this endpoint, including the price and/or quantity, apply to all future billing events unless changed subsequently.

  • When you add a subscription item, a history of revisions is created automatically.

🚧

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 Price and the Next Billing Date

Call the Get Subscription endpoint to retrieve the current subscription state and next billing date before performing the upgrade (NextBillingDate parameter of the API response).

Parameters

If the API call is formatted as described below, it will:

  • Calculate the next billing date if the renewal is made
  • Return the next billing date in the (so that it can be provided to the customer)
  • Not change any data in the Cleverbridge system.
ParameterTypeRequiredExampleNotes
SubscriptionIdstrYesS67439867The unique identifier of the subscription.

Request

curl --location 'https://rest.cleverbridge.com/subscription/getsubscription?subscriptionId=S67439867' 
--header 'Accept: application/json' 
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS' 
import http.client

conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = ''
headers = {
  'Accept': 'application/json',
  'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("GET", "/subscription/getsubscription?subscriptionId=S67439867", 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': 'GET',
  'hostname': 'rest.cleverbridge.com',
  'path': '/subscription/getsubscription?subscriptionId=S67439867',
  'headers': {
    '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);
  });
});

req.end();
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.get("https://rest.cleverbridge.com/subscription/getsubscription?subscriptionId=S67439867")
  .header("Accept", "application/json")
  .header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
  .asString();

Response

{
  "Subscription": {
    "Id": 67439867,
    "CustomerCurrencyId": "USD",
    "RenewalType": "Automatic",

    "StartDate": "2026-02-03T12:52:07.712033",
    "NextBillingDate": "2026-05-03T13:20:58.64752",
    "NextRenewalDate": "2026-05-03T13:20:58.64752",

    "NextBillingCustomerGrossPrice": 19.95,
    "NextBillingCustomerNetPrice": 16.76,
    "NextBillingCustomerVatPrice": 3.19,

    "Items": [
      {
        "RunningNo": 1,
        "ProductId": 293039,
        "ProductName": "Cloudify Bronze",
        "Quantity": 1,

        "IsCurrent": true,
        "Version": 8,

        "StartDate": "2026-02-03T12:52:07.712033",
        "VersionActiveDate": "2026-03-03T13:05:59.039403"
      }
    ],

    "PaymentInfo": {
      "PaymentType": "Visa",
      "CardLastFourDigits": "7654",
      "CardExpirationDate": {
        "Month": 12,
        "Year": 2027
      }
    }
  },

  "ResultMessage": "OK"
}

Step 2: Upgrade

Call the Update Subscription Item endpoint to replace the basic plan with the premium plan and renew subscription for another billing interval.

If the API call is formatted as described below, it will update the customer's subscription data in the Cleverbridge platform.

Parameter

Type

Required

Example

Notes

AlignmentSettings

obj

Yes

AlignToCurrentInterval: false

GetCustomerPricePreviewOnly: false

Applies the subscription change immediately as defined in the request.

ProductId

int

Yes

292122

The product ID for the Gold plan product (not the current Bronze plan product being replaced).

ResetBillingInterval

bool

Yes

true

Set to true to immediately start the new billing interval. If you use this option, you must also set TriggerImmediateRenewal to true.

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

S67439867

The unique identifier of the subscription.

UpdateAction

str

No

0

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

TriggerImmediateRenewal

bool

Yes

true

Triggers an immediate renewal and extends the next billing cycle by the remaining time in the current cycle.


📘

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": 292122,
    "ResetBillingInterval": true,
    "RunningNumber": 1,
    "Quantity": 1,
    "SubscriptionId": "S67439867",
    "UpdateAction": 0,
    "TriggerImmediateRenewal": true,
    "AlignmentSettings": {
        "AlignToCurrentInterval": false,
        "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": 292122,
    "ResetBillingInterval": true,
    "RunningNumber": 1,
    "Quantity": 1,
    "SubscriptionId": "S67439867",
    "UpdateAction": 0,
    "TriggerImmediateRenewal": true,
    "AlignmentSettings": {
        "AlignToCurrentInterval": false,
        "GetCustomerPricePreviewOnly": false
    }
}'
import http.client
import json

conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
  "ProductId": 292122,
  "ResetBillingInterval": True,
  "RunningNumber": 1,
  "Quantity": 1,
  "SubscriptionId": "S67439867",
  "UpdateAction": 0,
  "TriggerImmediateRenewal": True,
  "AlignmentSettings": {
    "AlignToCurrentInterval": False,
    "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": 292122,
  "ResetBillingInterval": true,
  "RunningNumber": 1,
  "Quantity": 1,
  "SubscriptionId": "S67439867",
  "UpdateAction": 0,
  "TriggerImmediateRenewal": true,
  "AlignmentSettings": {
    "AlignToCurrentInterval": false,
    "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\": 292122,\n    \"ResetBillingInterval\": true,\n    \"RunningNumber\": 1,\n    \"Quantity\": 1,\n    \"SubscriptionId\": \"S67439867\",\n    \"UpdateAction\": 0,\n    \"TriggerImmediateRenewal\": true,\n    \"AlignmentSettings\": {\n        \"AlignToCurrentInterval\": false,\n        \"GetCustomerPricePreviewOnly\": false\n    }\n}")
  .asString();

Response

{
    "ContinueUrl": "https://www.cleverbridge.com/864/p/538246861-iE1vkB7RnAbhZdJjsGbf",
    "NextBillingDate": "2026-05-16T12:37:52.772836",
    "NextRenewalDate": "2026-05-16T12:37:52.772836",
    "TransactionStatus": "Success",
    "AlignmentCustomerGrossPrice": 0.0,
    "AlignmentCustomerNetPrice": 0.0,
    "AlignmentCustomerVatPrice": 0.0,
    "NextBillingCustomerGrossPrice": 95.19,
    "NextBillingCustomerNetPrice": 79.99,
    "NextBillingCustomerVatPrice": 15.20,
    "NextRenewalCustomerGrossPrice": 95.19,
    "NextRenewalCustomerNetPrice": 79.99,
    "NextRenewalCustomerVatPrice": 15.20,
    "PriceCurrencyId": "USD",
    "ResultMessage": "OK"
}

Diagram

flowchart LR
  classDef mainColor fill:#ffffff,color:#555555,stroke:#96C34B,stroke-width:2px;

  A(["&nbsp;&nbsp;<br/><b>Upgrade</b><br/>The customer wants to upgrade <br/> before the end of the subscription interval&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> B(["&nbsp;&nbsp;<br/><b>Confirmation</b><br/>The customer confirms the plan change<br/> <i>Update Subscription Item</i> endpoint used&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> C(["&nbsp;&nbsp;<br/><b>Billing</b><br/>The full renewal price for the next billing interval starting immediately&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor