Add Item to a Subscription for Immediate Billing

Overview

This guide shows you how to implement the Add Subscription Item endpoint to add an additional item to a subscription and bill it immediately.

Use Case

Add an add-on immediately to an active subscription

Cloudify, a fictitious company, offers monthly cloud storage subscription. Their customer has run out of space and wants to purchase additional GB, available instantly.

To handle this, your system:

  1. Confirms the customer already has an active subscription.
  2. The customer clicks Buy now for the add-on.
  3. Your backend calls the Add Subscription Item endpoint.

Result:

Cleverbridge adds the new item to the existing subscription immediately and the customer is charged instantly.

The customer can use the new feature straight away, and the subscription now includes the additional item.

What Cloudify Shows the Customer (Example UI Summary)

Example image for illustration purposes only

Implement Add Subscription Item endpoint

To implement this use case, call the Add Subscription Item endpoint twice:

  1. Preview: Without changing data in the Cleverbridge platform using given parameters.
  2. Update the customer's subscription data in the Cleverbridge platform.

Before you start

Make sure that:

  • The subscription has the status Active.
  • All items in a subscription have the same billing interval.
  • Changes made by this function, including the price and/or quantity, apply to current and all future billing events unless changed subsequently.
🚧

Important

Get the customer's consent for changes to subscriptions. 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.

📘

Revisions history

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


Step 1: Preview of pro-rated billing amount

Preview of pro-rated billing amount (first call)

The API call:

  • Calculates the pro-rated price to be billed if the subscription item is added.
  • Returns the pro-rated billing amount in the AlignmentCustomerGrossPrice parameter of the API response (so that it can be provided to the customer).

Parameters

Parameter

Type

Required

Example

Notes

AlignmentSettings

obj

No

AlignToCurrentInterval: true
GetCustomerPricePreviewOnly: true

Does not change any data in the Cleverbridge system.

ProductId

int

Yes

293076

Product ID of the item you want to add to the subscription.

Quantity

int

Yes

1

The quantity of the new subscription item.

SubscriptionId

str

Yes

S67560422

The unique identifier of the subscription.

Request

curl --location --request POST 'https://rest.cleverbridge.com/subscription/addsubscriptionitem' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS' \
--data '{
  "SubscriptionId": "S67560422",
  "ProductId": 293076,
  "Quantity": 1,
  "AlignmentSettings": {
    "AlignToCurrentInterval": true,
    "GetCustomerPricePreviewOnly": true
  }
}'
import json
import urllib.request

url = "https://rest.cleverbridge.com/subscription/addsubscriptionitem"

payload = {
    "SubscriptionId": "S18577447",
    "ProductId": 97771,
    "Quantity": 1,
    "AlignmentSettings": {
        "AlignToCurrentInterval": True,
        "GetCustomerPricePreviewOnly": True
    },
    "CustomerPrice": {
        "CurrencyId": "EUR",
        "IsGross": True,
        "Value": 3.00
    }
}

req = urllib.request.Request(
    url=url,
    data=json.dumps(payload).encode("utf-8"),
    method="POST",
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": "Basic YOUR_BASE64_ENCODED_CREDENTIALS",
    },
)

with urllib.request.urlopen(req) as resp:
    print(resp.status)
    print(resp.read().decode("utf-8"))
const https = require('https');

const body = JSON.stringify({
  SubscriptionId: 'S67560422',
  ProductId: 293076,
  Quantity: 1,
  AlignmentSettings: {
    AlignToCurrentInterval: true,
    GetCustomerPricePreviewOnly: true
  }
});

// --- Auth (Basic Base64) ---
const username = 'myuser';
const password = 'mypassword';
const encoded = Buffer.from(`${username}:${password}`, 'utf8').toString('base64');

// --- HTTPS options ---
const options = {
  hostname: 'rest.cleverbridge.com',
  path: '/subscription/addsubscriptionitem',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': `Basic ${encoded}`,
    'Content-Length': Buffer.byteLength(body)
  }
};

// --- Request ---
const req = https.request(options, (res) => {
  let responseBody = '';

  console.log('Status:', res.statusCode);

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

  res.on('end', () => {
    try {
      console.log('JSON:', JSON.parse(responseBody));
    } catch {
      console.log('Body:', responseBody);
    }
  });
});

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

// Write JSON body and send request
req.write(body);
req.end();
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AddSubscriptionItemExample {
    public static void main(String[] args) throws Exception {
        String url = "https://rest.cleverbridge.com/subscription/addsubscriptionitem";

        // --- Auth (Basic Base64) ---
        String username = "myuser";
        String password = "mypassword";
        String creds = username + ":" + password;
        String encoded = Base64.getEncoder().encodeToString(creds.getBytes(StandardCharsets.UTF_8));

        // --- JSON Payload ---
        String json = """
        {
          "SubscriptionId": "S67560422",
          "ProductId": 293076,
          "Quantity": 1,
          "AlignmentSettings": {
            "AlignToCurrentInterval": true,
            "GetCustomerPricePreviewOnly": true
          }
        }
        """;

        // --- Request ---
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .header("Authorization", "Basic " + encoded)
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();

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

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

Response

{
  "AlignmentCustomerGrossPrice":9.64,
  "AlignmentCustomerNetPrice":8.10,
  "AlignmentCustomerVatPrice":1.54,
  "NextBillingCustomerGrossPrice":10.0,
  "NextBillingCustomerNetPrice":8.40,
  "NextBillingCustomerVatPrice":1.60,
  "NextRenewalCustomerGrossPrice":10.0,
  "NextRenewalCustomerNetPrice":8.40,
  "NextRenewalCustomerVatPrice":1.60,
  "PriceCurrencyId":"USD",
  "ResultMessage":"OK"
}

Step 2: Call Add item to the subscription

To update the customer's subscription data in the Cleverbridge platform, format the API call using the following parameters.

Parameters

Parameter

Type

Required

Example

Notes

AlignmentSettings

obj

No

AlignToCurrentInterval: true
GetCustomerPricePreviewOnly: false

Updates data in the Cleverbridge system.

ProductId

int

Yes

293076

Product ID of the item you want to add to the subscription.

Quantity

int

Yes

1

The quantity of the new subscription item.

SubscriptionId

str

Yes

S67560422

The unique identifier of the subscription.

Request

curl --location --request POST 'https://rest.cleverbridge.com/subscription/addsubscriptionitem' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS' \
--data '{
  "SubscriptionId": "S67560422",
  "ProductId": 293076,
  "Quantity": 1,
  "AlignmentSettings": {
    "AlignToCurrentInterval": true,
    "GetCustomerPricePreviewOnly": false
  }
}'
import json
import urllib.request

url = "https://rest.cleverbridge.com/subscription/addsubscriptionitem"

payload = {
    "SubscriptionId": "S67560422",
    "ProductId": 293076,
    "Quantity": 1,
    "AlignmentSettings": {
        "AlignToCurrentInterval": True,
        "GetCustomerPricePreviewOnly": False
    },

}

req = urllib.request.Request(
    url=url,
    data=json.dumps(payload).encode("utf-8"),
    method="POST",
    headers={
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": "Basic YOUR_BASE64_ENCODED_CREDENTIALS",
    },
)

with urllib.request.urlopen(req) as resp:
    print(resp.status)
    print(resp.read().decode("utf-8"))
const https = require('https');

const body = JSON.stringify({
  SubscriptionId: 'S67560422',
  ProductId: 293076,
  Quantity: 1,
  AlignmentSettings: {
    AlignToCurrentInterval: true,
    GetCustomerPricePreviewOnly: false
  }
});

// --- Auth (Basic Base64) ---
const username = 'myuser';
const password = 'mypassword';
const encoded = Buffer.from(`${username}:${password}`).toString('base64');

// --- HTTPS options ---
const options = {
  hostname: 'rest.cleverbridge.com',
  path: '/subscription/addsubscriptionitem',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': `Basic ${encoded}`,
    'Content-Length': Buffer.byteLength(body)
  }
};

// --- Request ---
const req = https.request(options, (res) => {
  let responseBody = '';

  console.log('Status:', res.statusCode);

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

  res.on('end', () => {
    try {
      console.log('JSON:', JSON.parse(responseBody));
    } catch {
      console.log('Body:', responseBody);
    }
  });
});

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

// Send request
req.write(body);
req.end();
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AddSubscriptionItem {
    public static void main(String[] args) throws Exception {
        String url = "https://rest.cleverbridge.com/subscription/addsubscriptionitem";
        String username = "myuser";
        String password = "mypassword";

        // Encode credentials to Base64
        String creds = username + ":" + password;
        String encoded = Base64.getEncoder().encodeToString(creds.getBytes(StandardCharsets.UTF_8));

        // JSON payload
        String json = """
        {
          "SubscriptionId": "S67560422",
          "ProductId": 293076,
          "Quantity": 1,
          "AlignmentSettings": {
            "AlignToCurrentInterval": true,
            "GetCustomerPricePreviewOnly": false
          }
        }
        """;

        // Build request
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .header("Authorization", "Basic " + encoded)
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();

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

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

Response

{
  "AlignmentCustomerGrossPrice":12.50,
  "AlignmentCustomerNetPrice":10.50,
  "AlignmentCustomerVatPrice":2.00,
  "NextBillingCustomerGrossPrice":3.0,
  "NextBillingCustomerNetPrice":2.52,
  "NextBillingCustomerVatPrice":0.48,
  "NextRenewalCustomerGrossPrice":3.0,
  "NextRenewalCustomerNetPrice":2.52,
  "NextRenewalCustomerVatPrice":0.48,
  "PriceCurrencyId":"EUR",
  "ResultMessage":"OK"
}