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

AlignToCurrentInterval: false GetCustomerPricePreviewOnly: false

Define the behavior when adding or updating a subscription item

CouponCode

str

YTY-DYT-F4A

Coupon code for a promotion

📘

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)

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(["&nbsp;&nbsp;<br/>A Cloudify customer contacts support<br/>to cancel their subscription&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> B(["&nbsp;&nbsp;<br/>A Cloudify support agent offers a discount<br/>&nbsp;"]):::mainColor
    --> C(["&nbsp;&nbsp;<br/>Cloudify calls <i>Update Subscription Item</i><br/>and sets the Coupon Code in the request&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor
    --> D(["&nbsp;&nbsp;<br/>The discount takes effect<br/>on the next billing date&nbsp;&nbsp;<br/>&nbsp;"]):::mainColor