List subscriptions
curl --request GET \
--url https://api-eu.flexportal.io/v1/subscriptions \
--header 'Authorization: Bearer <token>' \
--header 'Tenant-ID: <tenant-id>'import requests
url = "https://api-eu.flexportal.io/v1/subscriptions"
headers = {
"Tenant-ID": "<tenant-id>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'Tenant-ID': '<tenant-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api-eu.flexportal.io/v1/subscriptions', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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"
"net/http"
"io"
)
func main() {
url := "https://api-eu.flexportal.io/v1/subscriptions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Tenant-ID", "<tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-eu.flexportal.io/v1/subscriptions")
.header("Tenant-ID", "<tenant-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-eu.flexportal.io/v1/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Tenant-ID"] = '<tenant-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"rentals": [
{
"rentalId": "<string>",
"tenantId": "<string>",
"assetSerialNumber": "<string>",
"customerId": "<string>",
"sku": "<string>",
"productName": "<string>",
"monthlyAmount": 123,
"currency": "<string>",
"status": "active",
"originalContractLength": 123,
"contractLength": 123,
"startDate": "<string>",
"orderId": "<string>",
"customerEmail": "<string>",
"customerName": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>",
"createdBy": "<string>",
"productId": "<string>",
"variantId": "<string>",
"productImageUrl": "<string>",
"billingGroupId": "<string>",
"endDate": "<string>",
"nextBillingDate": "<string>",
"lastModifiedDate": "<string>",
"extensionHistory": [
{
"extensionMonths": 60,
"oldContractLength": 60,
"newContractLength": 60,
"oldMonthlyAmount": 1,
"newMonthlyAmount": 1,
"extendedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"oldEndDate": "<string>",
"newEndDate": "<string>",
"extendedAt": "<string>",
"reason": "<string>",
"notes": "<string>"
}
],
"actualMonthsRented": 123,
"monthsSaved": 123,
"listPrice": 123,
"listPriceSource": "variant",
"listPriceCapturedAt": "<string>",
"acquisitionCost": 123,
"acquisitionCostSource": "variant",
"acquisitionCostCapturedAt": "<string>",
"totalCollected": 123,
"costRecoveryPercent": 123,
"currentProfit": 123,
"breakevenMonths": 123,
"hasReachedBreakeven": true,
"recoveryStatus": "profitable",
"replacementHistory": [
{
"oldSerialNumber": "<string>",
"newSerialNumber": "<string>",
"reason": "<string>",
"replacedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"replacedAt": "<string>",
"damageAssessment": "<string>",
"insuranceClaim": true,
"notes": "<string>"
}
],
"buyoutDetails": {
"buyoutPrice": 1,
"calculationMethod": "auto_calculated",
"reason": "customer_request",
"processedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"buyoutDate": "<string>",
"calculationBreakdown": {
"remainingMonths": 60,
"remainingMonthsPayment": 1,
"listPricePercentage": 123,
"listPriceAmount": 1,
"flatFee": 1
},
"notes": "<string>"
},
"earlyReturnDetails": {
"fee": 1,
"feeWaived": true,
"calculationMethod": "auto_calculated",
"returnCondition": "excellent",
"reason": "<string>",
"processedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"returnedAt": "<string>",
"calculationBreakdown": {
"method": "remaining_months",
"remainingMonths": 60,
"gracePeriodApplied": true,
"daysFromStart": 1825
},
"damageAssessment": "<string>",
"notes": "<string>"
},
"cancellationDetails": {
"reason": "customer_request",
"processedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"cancelledAt": "<string>",
"notes": "<string>"
},
"upgradeFromRentalId": "<string>",
"customFields": {},
"notes": "<string>"
}
],
"count": 123,
"limit": 123,
"hasMore": true,
"nextCursor": "<string>"
}Subscriptions
List Subscriptions
Returns a paginated list of subscriptions.
GET
/
v1
/
subscriptions
List subscriptions
curl --request GET \
--url https://api-eu.flexportal.io/v1/subscriptions \
--header 'Authorization: Bearer <token>' \
--header 'Tenant-ID: <tenant-id>'import requests
url = "https://api-eu.flexportal.io/v1/subscriptions"
headers = {
"Tenant-ID": "<tenant-id>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'Tenant-ID': '<tenant-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api-eu.flexportal.io/v1/subscriptions', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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"
"net/http"
"io"
)
func main() {
url := "https://api-eu.flexportal.io/v1/subscriptions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Tenant-ID", "<tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-eu.flexportal.io/v1/subscriptions")
.header("Tenant-ID", "<tenant-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-eu.flexportal.io/v1/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Tenant-ID"] = '<tenant-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"rentals": [
{
"rentalId": "<string>",
"tenantId": "<string>",
"assetSerialNumber": "<string>",
"customerId": "<string>",
"sku": "<string>",
"productName": "<string>",
"monthlyAmount": 123,
"currency": "<string>",
"status": "active",
"originalContractLength": 123,
"contractLength": 123,
"startDate": "<string>",
"orderId": "<string>",
"customerEmail": "<string>",
"customerName": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>",
"createdBy": "<string>",
"productId": "<string>",
"variantId": "<string>",
"productImageUrl": "<string>",
"billingGroupId": "<string>",
"endDate": "<string>",
"nextBillingDate": "<string>",
"lastModifiedDate": "<string>",
"extensionHistory": [
{
"extensionMonths": 60,
"oldContractLength": 60,
"newContractLength": 60,
"oldMonthlyAmount": 1,
"newMonthlyAmount": 1,
"extendedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"oldEndDate": "<string>",
"newEndDate": "<string>",
"extendedAt": "<string>",
"reason": "<string>",
"notes": "<string>"
}
],
"actualMonthsRented": 123,
"monthsSaved": 123,
"listPrice": 123,
"listPriceSource": "variant",
"listPriceCapturedAt": "<string>",
"acquisitionCost": 123,
"acquisitionCostSource": "variant",
"acquisitionCostCapturedAt": "<string>",
"totalCollected": 123,
"costRecoveryPercent": 123,
"currentProfit": 123,
"breakevenMonths": 123,
"hasReachedBreakeven": true,
"recoveryStatus": "profitable",
"replacementHistory": [
{
"oldSerialNumber": "<string>",
"newSerialNumber": "<string>",
"reason": "<string>",
"replacedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"replacedAt": "<string>",
"damageAssessment": "<string>",
"insuranceClaim": true,
"notes": "<string>"
}
],
"buyoutDetails": {
"buyoutPrice": 1,
"calculationMethod": "auto_calculated",
"reason": "customer_request",
"processedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"buyoutDate": "<string>",
"calculationBreakdown": {
"remainingMonths": 60,
"remainingMonthsPayment": 1,
"listPricePercentage": 123,
"listPriceAmount": 1,
"flatFee": 1
},
"notes": "<string>"
},
"earlyReturnDetails": {
"fee": 1,
"feeWaived": true,
"calculationMethod": "auto_calculated",
"returnCondition": "excellent",
"reason": "<string>",
"processedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"returnedAt": "<string>",
"calculationBreakdown": {
"method": "remaining_months",
"remainingMonths": 60,
"gracePeriodApplied": true,
"daysFromStart": 1825
},
"damageAssessment": "<string>",
"notes": "<string>"
},
"cancellationDetails": {
"reason": "customer_request",
"processedBy": {
"userId": "<string>",
"email": "<string>",
"displayName": "<string>",
"role": "<string>",
"memberId": "<string>"
},
"cancelledAt": "<string>",
"notes": "<string>"
},
"upgradeFromRentalId": "<string>",
"customFields": {},
"notes": "<string>"
}
],
"count": 123,
"limit": 123,
"hasMore": true,
"nextCursor": "<string>"
}Overview
Retrieve a paginated list of subscriptions with optional filtering and sorting. Each subscription tracks billing, payments, cost recovery, and the complete lifecycle from activation to completion.Subscription Lifecycle
Order Created → Subscription Created → Active → [Extension/Upgrade/Buyout/Early Return] → Ended
- Contract completed: Reached end date naturally
- Buyout: Customer purchased the device
- Early return: Customer returned before contract end
- Cancellation: Terminated by operator
Common Use Cases
Active Subscriptions Dashboard
Monitor active subscriptions, MRR, and contract renewals
Operations Management
Track devices in the field, upcoming end dates, and required actions
Customer Support
Look up customer subscriptions during support inquiries
Financial Reporting
Generate reports on revenue, cost recovery, and profitability
Filtering Subscriptions
# Get all active subscriptions
GET /v1/subscriptions?status=active
# Get subscriptions for a customer
GET /v1/subscriptions?customerId=cust_abc123
# Get subscriptions ending this month
GET /v1/subscriptions?endDateFrom=2025-01-01&endDateTo=2025-01-31
# Get subscriptions by product SKU
GET /v1/subscriptions?sku=MACBOOK-PRO-16-M3
# Get subscriptions with specific asset
GET /v1/subscriptions?serialNumber=SN123456789
Subscription Status Values
| Status | Description |
|---|---|
active | Currently active subscription |
ended_completed | Contract completed naturally |
ended_buyout | Customer purchased the device |
ended_upgrade | Customer upgraded to a new device |
ended_early_return | Customer returned early |
cancelled | Subscription was cancelled |
Response Fields
Key fields in each subscription object:| Field | Description |
|---|---|
subscriptionId | Unique subscription identifier |
status | Current subscription status |
customerId | Associated customer ID |
orderId | Original order ID |
sku | Product variant SKU |
productName | Product display name |
serialNumber | Assigned asset serial number |
startDate | Subscription start date |
endDate | Subscription end date |
contractLength | Duration in months |
monthlyAmount | Monthly billing amount |
costRecovery | Cost recovery metrics |
createdAt | ISO 8601 timestamp |
Cost Recovery Metrics
Each subscription includes profitability data:{
"costRecovery": {
"acquisitionCost": 1800.00,
"totalCollected": 1548.00,
"costRecoveryPercent": 86.0,
"breakevenMonth": 14,
"monthsRemaining": 10
}
}
Example: Find Subscriptions Ending Soon
// Get subscriptions ending in the next 30 days
const today = new Date();
const thirtyDays = new Date(today.getTime() + 30 * 24 * 60 * 60 * 1000);
const { subscriptions } = await listSubscriptions({
status: 'active',
endDateFrom: today.toISOString().split('T')[0],
endDateTo: thirtyDays.toISOString().split('T')[0],
sortBy: 'endDate',
sortDir: 'asc'
});
// These customers might be interested in extensions or upgrades
for (const sub of subscriptions) {
console.log(`${sub.productName} (${sub.customerId}) ends ${sub.endDate}`);
}
Related Endpoints
- Get Subscription - Get detailed subscription info
- Create Subscription - Create subscription from order
- Extend Subscription - Extend contract period
- Buyout Subscription - Convert to purchase
Authorizations
API key obtained from FlexPortal dashboard
Headers
Your tenant identifier
Query Parameters
Items per page (default: 50, max: 100)
Cursor for pagination
Filter by status (active, cancelled, ended_completed, ended_buyout, ended_upgrade, ended_early_return)
Filter by customer ID
Filter by order ID
Filter by asset serial number
Was this page helpful?