Retain Customer with a Discount
Overview
This guide shows you how to implement the Update Subscription Item endpoint to offer a discount by adding a coupon code.
Use case
A Cloudify customer contacts support and says they want to cancel their subscription.
To retain the customer, a Cloudify support agent offers a discount for the subscription: either as a one-time retention offer or as an ongoing reduced price. Since the discount coupon is already configured in the Cleverbridge platform, the agent applies it directly to the customer’s subscription.
Cloudify then calls the Update Subscription Item endpoint and sets the CouponCode in the request.
The discount will take effect on the next billing date. Consecutive billing depends on the coupon settings in the Cleverbridge platform.
Considerations
- Single-item subscriptions only
- Takes effect on next billing event
- Discount remains until removed/changed
- Coupon must already exist in platform
Implement Update Subscription Item
Before you start
Make sure that:
- the subscription's status is Active
- the subscription has one item
- the coupon code is set in the Cleverbridge platform
Parameters
To update the customer's subscription data in the Cleverbridge platform, set the parameters in the Update Subscription Item API call to the values listed in the table.
Parameter | Type | Example | Notes |
|---|---|---|---|
SubscriptionId | str | S12345678 | The unique identifier for the customer's subscription. |
ProductId | int | 29899 | Product ID for the current Enterprise Hosting product associated with the subscription item. |
Quantity | int | 1 | Total number of items after the update. |
RunningNumber | int | 1 | Current number of subscription items. |
UpdateAction | str | upgrade | Used for documentation and tracking only. The value set does not affect transaction processing. See the Note below. |
AlignmentSettings | obj |
| Define the behavior when adding or updating a subscription item |
CouponCode | str | YTY-DYT-F4A | Coupon code for a promotion |
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)
Request
curl -X POST "https://rest.cleverbridge.com/subscriptions/S123456787/items/1" \
--header "Content-Type: application/json" \
--header "Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
--data '{
"ProductId": 29899,
"Quantity": 1,
"RunningNumber": 1,
"UpdateAction": "upgrade",
"AlignmentSettings": {
"AlignToCurrentInterval": false,
"GetCustomerPricePreviewOnly": false
},
"CouponCode": "YTY-DYT-F4A"
}'
import requests
import base64
import json
# Encode credentials: "username:password"
credentials = "YOUR_USERNAME:YOUR_PASSWORD"
encoded_credentials = base64.b64encode(credentials.encode()).decode()
url = "https://rest.cleverbridge.com/subscriptions/284947/items/1"
headers = {
"Content-Type": "application/json",
"Authorization": f"Basic {encoded_credentials}"
}
payload = {
"ProductId": 29899,
"Quantity": 1,
"RunningNumber": 1,
"UpdateAction": "upgrade",
"AlignmentSettings": {
"AlignToCurrentInterval": False,
"GetCustomerPricePreviewOnly": False
},
"CouponCode": "YTY-DYT-F4A"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.status_code)
print(response.text)
const axios = require("axios");
// Encode credentials: "username:password"
const credentials = Buffer.from("YOUR_USERNAME:YOUR_PASSWORD").toString("base64");
const url = "https://rest.cleverbridge.com/subscriptions/S12345678/items/1";
const headers = {
"Content-Type": "application/json",
"Authorization": `Basic ${credentials}`
};
const payload = {
ProductId: 29899,
Quantity: 1,
RunningNumber: 1,
UpdateAction: "upgrade",
AlignmentSettings: {
AlignToCurrentInterval: false,
GetCustomerPricePreviewOnly: false
},
CouponCode: "YTY-DYT-F4A"
};
axios
.post(url, payload, { headers })
.then(response => {
console.log("Status:", response.status);
console.log("Data:", response.data);
})
.catch(error => {
console.error("Error:", error.response?.data || error.message);
});
import java.io.*;
import java.net.*;
import java.util.Base64;
public class UpdateSubscriptionItem {
public static void main(String[] args) {
try {
String credentials = "YOUR_USERNAME:YOUR_PASSWORD";
String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes());
URL url = new URL("https://rest.cleverbridge.com/subscriptions/284947/items/1");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "Basic " + encodedCredentials);
conn.setDoOutput(true);
String jsonInputString = """
{
"ProductId": 29899,
"Quantity": 1,
"RunningNumber": 1,
"UpdateAction": "upgrade",
"AlignmentSettings": {
"AlignToCurrentInterval": false,
"GetCustomerPricePreviewOnly": false
},
"CouponCode": "YTY-DYT-F4A"
}
""";
try(OutputStream os = conn.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
int status = conn.getResponseCode();
System.out.println("Status Code: " + status);
try(BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println("Response: " + response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Response
{
"SubscriptionId": "S12345678",
"UpdatedItem": {
"RunningNumber": 1,
"ProductId": 29899,
"Quantity": 1,
"UpdateAction": "upgrade",
"AlignmentSettings": {
"AlignToCurrentInterval": false,
"GetCustomerPricePreviewOnly": false
},
"CouponCode": "YTY-DYT-F4A"
},
"Pricing": {
"Currency": "USD",
"ItemPrice": 49.99,
"DiscountAmount": 10.00,
"ProratedAmount": 8.33,
"TotalDueNow": 39.99
},
"SubscriptionPeriod": {
"Interval": "monthly",
"NextBillingDate": "2025-02-01T00:00:00Z",
"AlignedToExistingInterval": false
},
"Status": "Success",
"Message": "Subscription item updated successfully."
}
Diagram
flowchart LR
classDef mainColor fill:#ffffff,color:#96C34B,stroke:#96C34B,stroke-width:2px;
A([" <br/>A Cloudify customer contacts support<br/>to cancel their subscription <br/> "]):::mainColor
--> B([" <br/>A Cloudify support agent offers a discount<br/> "]):::mainColor
--> C([" <br/>Cloudify calls <i>Update Subscription Item</i><br/>and sets the Coupon Code in the request <br/> "]):::mainColor
--> D([" <br/>The discount takes effect<br/>on the next billing date <br/> "]):::mainColor
Updated 3 days ago