[API Guide] Align Subscription
Overview
This guide shows you how to implement the Align Subscriptions API endpoint to align multiple subscriptions to one billing interval.
Use case
A customer would like to align two monthly subscriptions, Cloudify Storage Monthly Renewal, and Cloudify M, so that they are billed on the same date.
Cloudify Storage Monthly Renewal is billed on the 27.05.2026 and in this case must be used as the primary subscription. The subscription, which is billed earlier, must be used as the secondary subscription.
| Subscription | Next Billing Date | Next Payment |
|---|---|---|
| Primary: Cloudify Storage Monthly Renewal | 27.05.2026 | $100.00 |
| Secondary: Cloudify M | 23.05.2026 | $2,000.00 |
The Align Subscriptions API endpoint is used to consolidate the date.
Result
Status change for the subscription
Primary and secondary subscriptions are now stacked in a single subscription with two items, and the same billing date.
The secondary subscription now has the status Finished and the Item Status Removed.
Secondary subscription
Implement the API endpoints
Before you start
Make sure that:
- Both subscriptions have the status
Active. - Both subscriptions have the same billing interval, for example, monthly.
- The currency type for both subscriptions is the same.
- Use the
AlignmentSettingsparameter for the subscription in the API response is required. Before doing so, see Get Started with Subscriptions > Alignment Settings. - Any changes made, including the price and/or quantity, apply to current and all future billing events unless modified subsequently.
- The billing amount is a positive number. A negative billing amount resulting from overpayments from a prior billing interval is not supported.
ImportantGet 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.
NoteUpdating the secondary subscription billing date could result in lost revenue for the adjusted billing interval.
Step 1: Alignment preview
Parameters
Parameter | Type | Required | Example | Notes |
|---|---|---|---|---|
AlignmentSettings | obj | Yes | AlignToCurrentInterval: true GetCustomerPricePreviewOnly: true | The subscription is NOT changed. |
PrimarySubscriptionId | str | Yes | S68574751 | The unique identifier of the primary subscription. |
SecondarySubscriptionId | str | Yes | S68618572 |
Request
curl --location 'https://rest.cleverbridge.com/subscription/alignsubscriptions'
--header 'Content-Type: application/json'
--header 'Accept: application/json'
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS'
--data '{
"PrimarySubscriptionId": "S68618572",
"SecondarySubscriptionId": "S68574751",
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": true
}
}'import http.client
import json
conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
"PrimarySubscriptionId": "S68618572",
"SecondarySubscriptionId": "S68574751",
"AlignmentSettings": {
"AlignToCurrentInterval": True,
"GetCustomerPricePreviewOnly": True
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("POST", "/subscription/alignsubscriptions", 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/alignsubscriptions',
'headers': {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
},
body: JSON.stringify({
"PrimarySubscriptionId": "S68618572",
"SecondarySubscriptionId": "S68574751",
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": true
}
})
};
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/alignsubscriptions")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
.body("{\n \"PrimarySubscriptionId\": \"S68618572\",\n \"SecondarySubscriptionId\": \"S68574751\",\n \"AlignmentSettings\": {\n \"AlignToCurrentInterval\": true,\n \"GetCustomerPricePreviewOnly\": true\n }\n}")
.asString();
Response
{
"AlignmentCustomerGrossPrice": 200.0,
"AlignmentCustomerNetPrice": 168.07,
"AlignmentCustomerVatPrice": 31.93,
"NextBillingCustomerGrossPrice": 2100.0,
"NextBillingCustomerNetPrice": 1764.70,
"NextBillingCustomerVatPrice": 335.30,
"NextRenewalCustomerGrossPrice": 2100.0,
"NextRenewalCustomerNetPrice": 1764.70,
"NextRenewalCustomerVatPrice": 335.30,
"PriceCurrencyId": "USD",
"ResultMessage": "OK"
}Step 2: Align subscriptions
Parameters
Parameter | Type | Required | Example | Notes |
|---|---|---|---|---|
AlignmentSettings | obj | Yes | AlignToCurrentInterval: true GetCustomerPricePreviewOnly: false | The subscription is changed as requested. |
PrimarySubscriptionId | str | Yes | S68618572 | The unique identifier of the primary subscription. |
SecondarySubscriptionId | str | Yes | S68574751 |
Request
curl --location 'https://rest.cleverbridge.com/subscription/alignsubscriptions'
--header 'Content-Type: application/json'
--header 'Accept: application/json'
--header 'Authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS'
--data '{
"PrimarySubscriptionId": "S68618572",
"SecondarySubscriptionId": "S68574751",
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": false
}
}'import http.client
import json
conn = http.client.HTTPSConnection("rest.cleverbridge.com")
payload = json.dumps({
"PrimarySubscriptionId": "S68618572",
"SecondarySubscriptionId": "S68574751",
"AlignmentSettings": {
"AlignToCurrentInterval": True,
"GetCustomerPricePreviewOnly": False
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
}
conn.request("POST", "/subscription/alignsubscriptions", 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/alignsubscriptions',
'headers': {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YOUR_BASE64_ENCODED_CREDENTIALS'
},
body: JSON.stringify({
"PrimarySubscriptionId": "S68618572",
"SecondarySubscriptionId": "S68574751",
"AlignmentSettings": {
"AlignToCurrentInterval": true,
"GetCustomerPricePreviewOnly": false
}
})
};
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/alignsubscriptions")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("Authorization", "Basic YOUR_BASE64_ENCODED_CREDENTIALS")
.body("{\n \"PrimarySubscriptionId\": \"S68618572\",\n \"SecondarySubscriptionId\": \"S68574751\",\n \"AlignmentSettings\": {\n \"AlignToCurrentInterval\": true,\n \"GetCustomerPricePreviewOnly\": false\n }\n}")
.asString();
Response
{
"AlignmentCustomerGrossPrice": 200.0,
"AlignmentCustomerNetPrice": 168.07,
"AlignmentCustomerVatPrice": 31.93,
"NextBillingCustomerGrossPrice": 2100.0,
"NextBillingCustomerNetPrice": 1764.70,
"NextBillingCustomerVatPrice": 335.30,
"NextRenewalCustomerGrossPrice": 2100.0,
"NextRenewalCustomerNetPrice": 1764.70,
"NextRenewalCustomerVatPrice": 335.30,
"PriceCurrencyId": "USD",
"ResultMessage": "OK"
}Updated 6 days ago