Extend a subscription
curl --request POST \
--url https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Tenant-ID: <tenant-id>' \
--data '
{
"rentalId": "<string>",
"extensionMonths": 60,
"reason": "<string>",
"newMonthlyAmount": 1,
"notes": "<string>"
}
'import requests
url = "https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend"
payload = {
"rentalId": "<string>",
"extensionMonths": 60,
"reason": "<string>",
"newMonthlyAmount": 1,
"notes": "<string>"
}
headers = {
"Tenant-ID": "<tenant-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Tenant-ID': '<tenant-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
rentalId: '<string>',
extensionMonths: 60,
reason: '<string>',
newMonthlyAmount: 1,
notes: '<string>'
})
};
fetch('https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'rentalId' => '<string>',
'extensionMonths' => 60,
'reason' => '<string>',
'newMonthlyAmount' => 1,
'notes' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Tenant-ID: <tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend"
payload := strings.NewReader("{\n \"rentalId\": \"<string>\",\n \"extensionMonths\": 60,\n \"reason\": \"<string>\",\n \"newMonthlyAmount\": 1,\n \"notes\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Tenant-ID", "<tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend")
.header("Tenant-ID", "<tenant-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"rentalId\": \"<string>\",\n \"extensionMonths\": 60,\n \"reason\": \"<string>\",\n \"newMonthlyAmount\": 1,\n \"notes\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Tenant-ID"] = '<tenant-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"rentalId\": \"<string>\",\n \"extensionMonths\": 60,\n \"reason\": \"<string>\",\n \"newMonthlyAmount\": 1,\n \"notes\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"rentalId": "<string>",
"assetSerialNumber": "<string>",
"oldEndDate": "<string>",
"newEndDate": "<string>",
"extensionMonths": 60,
"oldContractLength": 60,
"newContractLength": 60
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}Subscriptions
Extend Subscription
Extends the subscription contract length.
POST
/
v1
/
subscriptions
/
{subscriptionId}
/
extend
Extend a subscription
curl --request POST \
--url https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Tenant-ID: <tenant-id>' \
--data '
{
"rentalId": "<string>",
"extensionMonths": 60,
"reason": "<string>",
"newMonthlyAmount": 1,
"notes": "<string>"
}
'import requests
url = "https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend"
payload = {
"rentalId": "<string>",
"extensionMonths": 60,
"reason": "<string>",
"newMonthlyAmount": 1,
"notes": "<string>"
}
headers = {
"Tenant-ID": "<tenant-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Tenant-ID': '<tenant-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
rentalId: '<string>',
extensionMonths: 60,
reason: '<string>',
newMonthlyAmount: 1,
notes: '<string>'
})
};
fetch('https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'rentalId' => '<string>',
'extensionMonths' => 60,
'reason' => '<string>',
'newMonthlyAmount' => 1,
'notes' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Tenant-ID: <tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend"
payload := strings.NewReader("{\n \"rentalId\": \"<string>\",\n \"extensionMonths\": 60,\n \"reason\": \"<string>\",\n \"newMonthlyAmount\": 1,\n \"notes\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Tenant-ID", "<tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend")
.header("Tenant-ID", "<tenant-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"rentalId\": \"<string>\",\n \"extensionMonths\": 60,\n \"reason\": \"<string>\",\n \"newMonthlyAmount\": 1,\n \"notes\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/extend")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Tenant-ID"] = '<tenant-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"rentalId\": \"<string>\",\n \"extensionMonths\": 60,\n \"reason\": \"<string>\",\n \"newMonthlyAmount\": 1,\n \"notes\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"rentalId": "<string>",
"assetSerialNumber": "<string>",
"oldEndDate": "<string>",
"newEndDate": "<string>",
"extensionMonths": 60,
"oldContractLength": 60,
"newContractLength": 60
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}Overview
Extend an active subscription’s contract period. Extensions allow customers to keep their device longer than the original contract term, typically at a reduced monthly rate.When to Use Extensions
Extension Benefits
- For customers: Keep familiar device at lower monthly cost
- For operators: Continue earning revenue on fully depreciated assets
- For both: No logistics costs (no return/ship new device)
Request Fields
| Field | Required | Description |
|---|---|---|
extensionMonths | Yes | Number of months to extend |
newMonthlyAmount | No | New monthly price (default: current price) |
reason | No | Reason for extension |
Basic Example
{
"extensionMonths": 6
}
Example with Price Adjustment
{
"extensionMonths": 12,
"newMonthlyAmount": 79.00,
"reason": "Loyalty discount for renewal"
}
Extensions are a great opportunity to offer loyalty discounts. Assets are often fully paid off by the end of the initial contract, so lower extension rates can still be highly profitable.
What Happens
When you extend a subscription:- End date pushed forward by extension months
- Contract length updated to reflect total duration
- Monthly amount updated (if new price provided)
- Extension history logged with details
- Future payments scheduled at new rate
Pricing Strategy for Extensions
// Example: Calculate extension pricing
function calculateExtensionPrice(subscription, extensionMonths) {
const currentMonthly = subscription.monthlyAmount;
const costRecovery = subscription.costRecovery.costRecoveryPercent;
if (costRecovery >= 100) {
// Asset is paid off - offer 30% discount
return currentMonthly * 0.7;
} else if (costRecovery >= 80) {
// Almost paid off - offer 20% discount
return currentMonthly * 0.8;
} else {
// Still recovering costs - keep same price
return currentMonthly;
}
}
Extension History
After extending, the subscription tracks extension history:{
"extensionHistory": [
{
"extendedAt": "2025-01-15T10:30:00Z",
"extensionMonths": 6,
"previousEndDate": "2025-01-31",
"newEndDate": "2025-07-31",
"previousMonthlyAmount": 129.00,
"newMonthlyAmount": 99.00,
"reason": "Customer renewal"
}
]
}
Common Extension Periods
| Period | Typical Use |
|---|---|
| 3 months | Short-term bridge while waiting for upgrade |
| 6 months | Standard renewal for satisfied customers |
| 12 months | Full year renewal with loyalty discount |
| 24 months | Long-term commitment with best pricing |
Error Handling
| Error Code | Cause | Solution |
|---|---|---|
SUBSCRIPTION_NOT_ACTIVE | Subscription is not active | Can only extend active subscriptions |
INVALID_EXTENSION_MONTHS | Extension months must be positive | Use positive integer |
Related Endpoints
- Get Subscription - Check current subscription details
- Upgrade Subscription - Upgrade to different device
- Buyout Subscription - Convert to purchase
- List Subscriptions - Find subscriptions to extend
Authorizations
API key obtained from FlexPortal dashboard
Headers
Your tenant identifier
Path Parameters
The subscription ID
Body
application/json
Response
Extension completed
Available options:
true Required range:
0 <= x <= 120Required range:
1 < x <= 120Required range:
1 < x <= 120Was this page helpful?