Customize Subscription Renewal Price

Overview

This guide shows you how to implement the Get Subscription and the Update Subscription Item Price API endpoints to customize subscription renewal price.

Use Case

  1. A Cloudify customer plans to buy more seats in the future and asks for a price reduction.
  2. Cloudify agrees and reduces the price per seat from $5.00 to $4.85.
  3. Cloudify updates the subscription seat price using the Update Subscription Item Price API endpoint. 
  4. Cleverbridge automatically renews the subscription and bills the customer.

Implement API endpoints

Before you start

Make sure that:

  • The subscription has the status Active.
  • Any changes made, including the price and/or quantity, apply to all future billing events unless modified subsequently.
  • Use of the CustomerPrice parameter in the API response is required.
    Before doing so, see Understand Customer Price.
  • Use the AlignmentSettings parameter for the subscription in the API response is required.
    Before doing so, see Get Started with Subscription API > Alignment Settings.

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: Retrieve the Quantity of Users

To retrieve the current subscription item quantity:

  1. Call the Get Subscription API endpoint.
  2. In the SubscriptionItem array data returned in the response, locate the single instance in the array for which both of the following statements are true:
  • RunningNumber matches the running number of the subscription item for which the quantity is needed.
  • The IsCurrent parameter is true.
  1. Retrieve the current quantity for the Users subscription item from this instance of the array.

Parameters

ParameterTypeRequiredExampleNotes
RunningNumberintYes1Running number of the item in the subscription.
SubscriptionIdstrYesS67531904The unique identifier of the subscription.
isCurrentboolYestrueWhether to return only the current state.

Request

curl --request GET \
  --url "https://rest.cleverbridge.com/subscription/getsubscription?RunningNumber=1&SubscriptionId=S67531904&isCurrent=true" \
  --header "Accept: application/json" \
  --header "Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
import json
from urllib.parse import urlencode
from urllib.request import Request, urlopen

BASE_URL = "https://rest.cleverbridge.com/subscription/getsubscription"

params = {
    "RunningNumber": 1,
    "SubscriptionId": "S67531904",
    "isCurrent": "true"
}

query_string = urlencode(params)
url = f"{BASE_URL}?{query_string}"

req = Request(
    url,
    method="GET",
    headers={
        "Accept": "application/json",
        "Authorization": "Basic YOUR_BASE64_ENCODED_CREDENTIALS"
    }
)

with urlopen(req) as resp:
    body = resp.read().decode("utf-8")
    print("Status:", resp.status)
    print(json.dumps(json.loads(body), indent=2))
const https = require("https");

const baseUrl = "https://rest.cleverbridge.com";
const path =
  "/subscription/getsubscription?RunningNumber=1&SubscriptionId=S67531904&isCurrent=true";

const options = {
  method: "GET",
  headers: {
    Accept: "application/json",
    Authorization: "Basic YOUR_BASE64_ENCODED_CREDENTIALS",
  },
};

const req = https.request(baseUrl + path, options, (res) => {
  let data = "";

  res.on("data", (chunk) => {
    data += chunk;
  });

  res.on("end", () => {
    console.log("Status:", res.statusCode);
    try {
      console.log(JSON.stringify(JSON.parse(data), null, 2));
    } catch {
      console.log(data);
    }
  });
});

req.on("error", (err) => {
  console.error("Request error:", err);
});

req.end();
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class GetSubscriptionSample {

    public static void main(String[] args) throws IOException, InterruptedException {

        String baseUrl = "https://rest.cleverbridge.com/subscription/getsubscription";

        String query =
            "RunningNumber=" + URLEncoder.encode("1", StandardCharsets.UTF_8) +
            "&SubscriptionId=" + URLEncoder.encode("S67531904", StandardCharsets.UTF_8) +
            "&isCurrent=" + URLEncoder.encode("true", StandardCharsets.UTF_8);

        String url = baseUrl + "?" + query;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .header("Accept", "application/json")
            .header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
            .GET()
            .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println("Status: " + response.statusCode());
        System.out.println(response.body());
    }
}

Response

From the Items object, retrieve the quantity of the subscription seats. Example: "Quantity": 10

{
    "Subscription": {
        "CustomerCurrencyId": "USD",
        "CustomerId": 157610360,
        "CustomerReferenceId": "MbZHngtCou1wRCBahnccYkNqsVdpgc6Fl9hzENQ1",
        "CustomerReferenceNo": "",
        "EndDate": null,
        "GracePeriodDays": 0,
        "Id": 67531904,
        "IntervalDayCount": 0,
        "IntervalMonthCount": 1,
        "BillingIntervalDayCount": 0,
        "BillingIntervalMonthCount": 0,
        "Items": [
            {
                "Couponcode": "",
                "DeactivationDate": null,
                "EndDate": null,
                "IsCurrent": true,
                "LastIntervalNo": 0,
                "NextBillingCurrencyId": "USD",
                "NextBillingCustomerGrossPrice": 50.0,
                "NextBillingCustomerNetPrice": 42.02,
                "NextBillingCustomerVatPrice": 7.98,
                "NextRenewalCustomerGrossPrice": 50.0,
                "NextRenewalCustomerNetPrice": 42.02,
                "NextRenewalCustomerVatPrice": 7.98,
                "ProductId": 292973,
                "ProductName": "Cloudify Seat",
                "ProductNameExtension": "",
                "PromotionId": null,
                "Quantity": 10,               //the quantity of the subscription seats.
																	
                "RecurrenceCount": null,
                "RunningNo": 1,
                "StartDate": "2026-02-09T15:43:07.20517",
                "Status": 1,
                "SubscriptionId": 67531904,
                "SubscriptionPurchaseItems": [
                    {
                        "PurchaseId": 531157892,
                        "PurchaseItemRunningNo": 1,
                        "SubscriptionIntervalNo": 0,
                        "BillingIntervalNo": 0
                    }
                ],
                "Version": 1,
                "VersionActiveDate": "2026-02-09T15:43:07.20517"
            }
        ],
        "LastIntervalNo": 0,
        "LastBillingIntervalNo": 0,
        "NextBillingCurrencyId": "USD",
        "NextBillingCustomerGrossPrice": 50.0,
        "NextBillingCustomerNetPrice": 42.02,
        "NextBillingCustomerVatPrice": 7.98,
        "NextRenewalCustomerGrossPrice": 50.0,
        "NextRenewalCustomerNetPrice": 42.02,
        "NextRenewalCustomerVatPrice": 7.98,
        "NextBillingDate": "2026-03-09T15:43:07.20517",
        "NextRenewalDate": "2026-03-09T15:43:07.20517",
        "NextBillingDateReminder": "2026-03-07T15:43:07.20517Z",
        "PaymentInfo": {
            "CardExpirationDate": {
                "Month": 12,
                "Year": 2027
            },
            "CardLastFourDigits": "765T",
            "Currency": null,
            "CurrencyId": null,
            "IsPurchaseOrder": null,
            "PaymentType": "Visa",
            "PaymentTypeId": "CCA_VIS"
        },
        "RenewalType": "Automatic",
        "StartDate": "2026-02-09T15:43:07.20517",
        "StartIntervalDayCount": 0,
        "StartIntervalMonthCount": 1,
        "Subscriptionstatus": 1,
        "ManagementModel": "One",
        "SelfServiceUrl": "https://www.cleverbridge.com/864/s/s67531904-VlWdITPJkw6s6kFr"
    },
    "ResultMessage": "OK"
}

Step 2: Update Subscription Item Price

Set the parameters in the Update Subscription Item Price API call to the values listed in the table.

Parameter

Type

Required

Example

Notes

AlignmentSettings

obj

No

AlignToCurrentInterval: false

GetCustomerPricePreviewOnly: false

The subscription is changed as requested in the API call.

CustomerPrice

obj

Yes

CurrencyId: USD

IsGross: true

Value: 4.00

Set new price at $4.00

Quantity

int

Yes

20

Number of seats in the subscription.

RunningNumber

int

Yes

1

Running number of the item in the subscription.

SubscriptionId

str

Yes

S67531904

The unique identifier of the subscription.

UpdateAction

str

No

upgrade

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

{
    "SubscriptionId": "S67531904",
    "RunningNumber": 1,
    "UpdateAction": "upgrade",
    "ForcePriceRecalculation": false,
    "Quantity": 20,
    "CustomerPrice": {
        "CurrencyId": "USD",
        "IsGross": true,
        "Value": 4.0
    },
    "AlignmentSettings": {
        "AlignToCurrentInterval": false,
        "GetCustomerPricePreviewOnly": false,
        "GetCustomerPricePreviewOnly": false
    }
}

Request

curl --location 'https://rest.cleverbridge.com/subscription/updatesubscriptionitemprice' 
--header 'Content-Type: application/json' 
--header 'Accept: application/json' 
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS' 
--data '{
    "SubscriptionId": "S67531904",
    "RunningNumber": 1,
    "UpdateAction": "upgrade",
    "ForcePriceRecalculation": false,
    "Quantity": 20,
    "CustomerPrice": {
        "CurrencyId": "USD",
        "IsGross": true,
        "Value": 4.0
    },
    "AlignmentSettings": {
      "AlignToCurrentInterval": false,
      "GetCustomerPricePreviewOnly": false,
      "GetCustomerPricePreviewOnly": false
    }
  }'
import http.client
import json

conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
  "SubscriptionId": "S67531904",
  "RunningNumber": 1,
  "UpdateAction": "upgrade",
  "Quantity": 20,
  "ForcePriceRecalculation": False,
  "CustomerPrice": {
    "CurrencyId": "USD",
    "IsGross": True,
    "Value": 4.00
  },
  "AlignmentSettings": {
    "AlignToCurrentInterval": False,
    "GetCustomerPricePreviewOnly": False
  }
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("POST", "/subscription/updatesubscriptionitemprice", 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/updatesubscriptionitemprice',
  '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({
  "SubscriptionId": "S67531904",
  "RunningNumber": 1,
  "UpdateAction": "upgrade",
  "ForcePriceRecalculation": false,
  "Quantity": 20,
  "CustomerPrice": {
    "CurrencyId": "USD",
    "IsGross": true,
    "Value": 4.00
  },
  "AlignmentSettings": {
    "AlignToCurrentInterval": false,
    "GetCustomerPricePreviewOnly": false
  }
});

req.write(postData);

req.end();
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://rest.cleverbridge.com/subscription/updatesubscriptionitemprice")
  .header("Content-Type", "application/json")
  .header("Accept", "application/json")
  .header("Authorization", "Basic YW5uYS5rdWxjenlja2E6QExvZWJhdWVyMjAyNg==")
  .body("{\n    \"SubscriptionId\": \"S67531904\",\n    \"RunningNumber\": 1,\n    \"UpdateAction\": \"upgrade\",\n    \"ForcePriceRecalculation\": false,\n    \"Quantity\": 20,\n    \"CustomerPrice\": {\n        \"CurrencyId\": \"USD\",\n        \"IsGross\": true,\n        \"Value\": 4.0\n    },\n    \"AlignmentSettings\": {\n        \"AlignToCurrentInterval\": false,\n        \"GetCustomerPricePreviewOnly\": false,\n        \"GetCustomerPricePreviewOnly\": false\n    }\n}")
  .asString();

Diagram

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

  A(["&nbsp;&nbsp;<br/>A Cloudify customer wants to buy more seats<br/>and asks for a discount&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> B(["&nbsp;&nbsp;<br/>Cloudify reduces the price per seat<br/>from $5.00 to $4.85&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> C(["&nbsp;&nbsp;<br/>Cleverbridge automatically renews the subscription<br/>and bills the customer&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor