Renew a Data-Limited Subscription Early at a Custom Price

Overview

This guide shows you how to implement the Update Subscription Item and Renew Subscription API endpoints to renew the customer's subscription immediately at a custom price.

Use case

  1. The customer reaches their data limit and considers canceling their subscription.

  2. Cloudify directs the customer to a page that calls the Update Subscription Item API endpoint to retrieve and display the updated subscription details, including a custom price and new expiration date.

  3. The customer clicks Renew Now. Cloudify uses the Renew Subscription API endpoint to immediately renew the subscription at a custom price.

    The new billing interval starts immediately, and the customer is shown a confirmation page (or error handling if the payment fails).

Implement Update Subscription Item API endpoint

Before you start

🚧

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.


Make sure that:

  • The current billing interval has started and the next billing date has not yet been reached.
  • Any changes made, including the price and/or quantity, apply to all future billing events unless modified subsequently.
  • The renewal is not combined with an alignment of the subscription.

Step 1: Update the subscription item

Call the Update Subscription Item API endpoint to retrieve and display the updated subscription details to the customer.

Parameters

Parameter

Type

Required

Example

Notes

AlignmentSettings

obj

Yes

AlignToCurrentInterval: false

GetCustomerPricePreviewOnly: false

The subscription is changed as requested in the API call.
See Alignment Settings for more information.

CustomerPrice

obj

Yes

"CurrencyId": "EUR", "IsGross": true, "Value": 80.00

See Understand Customer Price for more details.

ProductId

int

Yes

293103

ID of the product to be updated.

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

S67661151

The unique identifier of the subscription.

UpdateAction

str

Yes

Update

The value does not affect transaction processing.

The renewal is not combined with an alignment of the subscription. Therefore, AlignToCurrentInterval must be set to 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": 293103,
  "Quantity": 1,
  "RunningNumber": 1,
  "SubscriptionId": "S67632293",
  "UpdateAction": 0,
  "AlignmentSettings": {
    "AlignToCurrentInterval": false,
    "GetCustomerPricePreviewOnly": false
  },
  "CustomerPrice": {
    "CurrencyId": "USD",
    "IsGross": true,
    "Value": 80.00
  }
}'
import http.client
import json

conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
  "ProductId": 293103,
  "Quantity": 1,
  "RunningNumber": 1,
  "SubscriptionId": "S67632293",
  "UpdateAction": 0,
  "AlignmentSettings": {
    "AlignToCurrentInterval": False,
    "GetCustomerPricePreviewOnly": False
  },
  "CustomerPrice": {
    "CurrencyId": "USD",
    "IsGross": True,
    "Value": 80
  }
})
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 request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://rest.cleverbridge.com/subscription/updatesubscriptionitem',
  'headers': {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS',
  },
  body: JSON.stringify({
    "ProductId": 293103,
    "Quantity": 1,
    "RunningNumber": 1,
    "SubscriptionId": "S67632293",
    "UpdateAction": 0,
    "AlignmentSettings": {
      "AlignToCurrentInterval": false,
      "GetCustomerPricePreviewOnly": false
    },
    "CustomerPrice": {
      "CurrencyId": "USD",
      "IsGross": true,
      "Value": 80
    }
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});
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\": 293103,\n  \"Quantity\": 1,\n  \"RunningNumber\": 1,\n  \"SubscriptionId\": \"S67632293\",\n  \"UpdateAction\": 0,\n  \"AlignmentSettings\": {\n    \"AlignToCurrentInterval\": false,\n    \"GetCustomerPricePreviewOnly\": false\n  },\n  \"CustomerPrice\": {\n    \"CurrencyId\": \"USD\",\n    \"IsGross\": true,\n    \"Value\": 80.00\n  }\n}")
  .asString();

JSON body

{
   "ProductId": 293103,
  "Quantity": 1,
  "RunningNumber": 1,
  "SubscriptionId": "S67632293",
  "UpdateAction": "Update",
  "AlignmentSettings": {
    "AlignToCurrentInterval": false,
    "GetCustomerPricePreviewOnly": false
  },
  "CustomerPrice": {
    "CurrencyId": "USD",
    "IsGross": true,
    "Value": 80.00
  }
}

Response

{
    "AlignmentCustomerGrossPrice": 0.0,
    "AlignmentCustomerNetPrice": 0.0,
    "AlignmentCustomerVatPrice": 0.0,
    "NextBillingCustomerGrossPrice": 80.00,
    "NextBillingCustomerNetPrice": 67.23,
    "NextBillingCustomerVatPrice": 12.77,
    "NextRenewalCustomerGrossPrice": 80.00,
    "NextRenewalCustomerNetPrice": 67.23,
    "NextRenewalCustomerVatPrice": 12.77,
    "PriceCurrencyId": "USD",
    "ResultMessage": "OK"
}

Use ContinueUrl to redirect the customer to the Cleverbridge confirmation page after the renewal request is processed.
If the transaction is not successful, the page linked in the ContinueUrl field will inform the customer about the next steps, such as updating the payment details in case of a failed payment.

Step 2: Renew the subscription

Call the Renew Subscription API endpoint to renew the subscription immediately.

Parameters

ParameterTypeRequiredExampleNotes
SubscriptionIdstrYesS67632293The unique identifier of the subscription.
ResetBillingIntervalboolYestrueSet to true to immediately start the new billing interval.

Request

curl --location 'https://rest.cleverbridge.com/subscription/renewsubscription' 
--header 'Content-Type: application/json' 
--header 'Accept: application/json' 
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS' 
--data '{
    "SubscriptionId": "S67632293",
    "ResetBillingInterval": true
}'
import http.client
import json

conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
  "SubscriptionId": "S67632293",
  "ResetBillingInterval": True
})
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("POST", "/subscription/renewsubscription", 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/renewsubscription',
  '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": "S67632293",
  "ResetBillingInterval": true
});

req.write(postData);

req.end();
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://rest.cleverbridge.com/subscription/renewsubscription")
  .header("Content-Type", "application/json")
  .header("Accept", "application/json")
  .header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
  .body("{\n    \"SubscriptionId\": \"S67632293\",\n    \"ResetBillingInterval\": true\n}")
  .asString();

Response

{
    "ContinueUrl": "https://www.cleverbridge.com/864/p/537553211-Fi9tRfI9abgAJdNFxcsd",
    "NextBillingDate": "2026-05-09T13:16:19.677779",
    "TransactionStatus": "Success",
    "ResultMessage": "OK"
}

Diagram

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

  A(["&nbsp;&nbsp;<br/><b>Data limit reached</b><br/>The customer reaches their data limit and considers canceling their subscription&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> B(["&nbsp;&nbsp;<br/><b>New price offered</b><br/>Cloudify offers a new price using <i>Update Subscription Item</i> API endpoint&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> C(["&nbsp;&nbsp;<br/><b>Renewal</b><br/>Cloudify uses <i>Renew Subscription</i> API endpoint to immediately renew the subscription at a custom price&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor