Skip to main content
POST
/
v1
/
subscriptions
/
{subscriptionId}
/
upgrade
Upgrade a subscription
curl --request POST \
  --url https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/upgrade \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Tenant-ID: <tenant-id>' \
  --data '
{
  "rentalId": "<string>",
  "newSku": "<string>",
  "newSerialNumber": "<string>",
  "contractLength": 60,
  "newMonthlyAmount": 1,
  "reason": "<string>",
  "notes": "<string>"
}
'
{
  "success": true,
  "message": "<string>",
  "oldRentalId": "<string>",
  "newRentalId": "<string>",
  "oldDevice": "<string>",
  "newDevice": "<string>",
  "newMonthlyAmount": 1,
  "currency": "<string>"
}

Overview

Upgrade a customer to a different (typically better) device. This ends the current subscription and creates a new order for the upgraded product. The customer returns their current device and receives a new one.

When to Use Upgrades

ScenarioUse This
Customer wants newer/better deviceUpgrade
Customer wants same device longerExtend
Current device is faultyReplace
Customer wants to own current deviceBuyout

Upgrade Flow

1. Calculate upgrade terms
2. Call upgrade endpoint
3. Current subscription marked for end
4. New upgrade order created
5. Customer returns old device
6. New device shipped
7. New subscription starts

Request Fields

FieldRequiredDescription
newSkuYesSKU of the upgrade product
newContractLengthYesContract length for new subscription
reasonNoReason for upgrade

Example Request

{
  "newSku": "MACBOOK-PRO-16-M4",
  "newContractLength": 24,
  "reason": "Customer requested latest model"
}

What Happens

When you process an upgrade:
  1. Current subscription marked as ending (status changes on return)
  2. Upgrade order created with type upgrade
  3. Order linked to original subscription for tracking
  4. Pricing calculated based on new variant’s rates
  5. Return scheduled for current device

Response Structure

{
  "success": true,
  "message": "Upgrade order created",
  "upgradeOrderId": "ord_xyz789",
  "currentSubscription": {
    "subscriptionId": "sub_abc123",
    "scheduledEndDate": "2025-02-15"
  },
  "upgradeDetails": {
    "previousDevice": "MacBook Pro 16\" M3",
    "newDevice": "MacBook Pro 16\" M4",
    "previousMonthlyAmount": 129.00,
    "newMonthlyAmount": 159.00
  }
}

Upgrade Pricing Considerations

Consider these factors when setting upgrade prices:
  • Remaining value on current device
  • New device acquisition cost
  • Market rates for the new device
  • Customer loyalty and history
// Example: Check if upgrade makes sense
async function analyzeUpgrade(subscriptionId, newSku) {
  const subscription = await getSubscription(subscriptionId);
  const newVariant = await getVariantBySku(newSku);

  return {
    currentMonthly: subscription.monthlyAmount,
    newMonthly: newVariant.pricing['24'], // 24-month price
    monthlyCostIncrease: newVariant.pricing['24'] - subscription.monthlyAmount,
    currentDeviceReturn: subscription.serialNumber,
    recommendation: newVariant.pricing['24'] > subscription.monthlyAmount
      ? 'upsell'
      : 'downgrade'
  };
}

Completing the Upgrade

After calling upgrade:
  1. Process the return of the current device
  2. Create subscription on the upgrade order (like any new order)
  3. Ship the new device to customer

Error Handling

Error CodeCauseSolution
SUBSCRIPTION_NOT_ACTIVECannot upgrade inactive subscriptionCheck subscription status
VARIANT_NOT_FOUNDNew SKU doesn’t existVerify SKU in product catalog
VARIANT_INACTIVENew SKU is deactivatedUse an active variant
INVALID_CONTRACT_LENGTHContract length not supportedUse valid contract length

Authorizations

Authorization
string
header
required

API key obtained from FlexPortal dashboard

Headers

Tenant-ID
string
required

Your tenant identifier

Path Parameters

subscriptionId
string
required

The subscription ID

Body

application/json
rentalId
string
required
Minimum string length: 1
newSku
string
required
Minimum string length: 1
newSerialNumber
string
required
Minimum string length: 1
contractLength
integer
required
Required range: 1 < x <= 120
newMonthlyAmount
number
required
Required range: x >= 0
reason
string
required
Minimum string length: 1
notes
string

Response

Upgrade completed

success
enum<boolean>
required
Available options:
true,
false
message
string
required
oldRentalId
string
required
newRentalId
string
required
oldDevice
string
required
newDevice
string
required
newMonthlyAmount
number
required
Required range: x >= 0
currency
string
required