Skip to main content
POST
/
v1
/
subscriptions
/
{subscriptionId}
/
buyout
Buyout a subscription
curl --request POST \
  --url https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/buyout \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Tenant-ID: <tenant-id>' \
  --data '
{
  "rentalId": "<string>",
  "reason": "customer_request",
  "buyoutPrice": 1,
  "notes": "<string>"
}
'
{
  "success": true,
  "rentalId": "<string>",
  "assetSerialNumber": "<string>",
  "buyoutPrice": 1,
  "currency": "<string>",
  "effectiveDate": "<string>",
  "message": "<string>"
}

Overview

Process a buyout to convert a subscription into a purchase. The customer pays a buyout price and keeps the device permanently. This ends the subscription and transfers ownership of the asset.

When to Offer Buyouts

ScenarioBuyout Makes Sense
Near end of contractCustomer wants to keep device
Cost fully recoveredAsset is paid off, buyout is pure profit
Customer preferenceCustomer prefers ownership
Old inventorySimplify operations by selling older devices

Buyout Pricing

Before processing a buyout, calculate the price using Calculate Buyout. Buyout prices typically consider:
  • Remaining contract value: Unpaid months × monthly rate
  • Residual value: Expected asset value at contract end
  • Cost recovery status: How much you’ve already collected
// Common buyout formula
const remainingMonths = subscription.monthsRemaining;
const monthlyAmount = subscription.monthlyAmount;
const residualValue = 200; // Tenant-configured minimum

const buyoutPrice = (remainingMonths * monthlyAmount) + residualValue;

Request Fields

FieldRequiredDescription
buyoutPriceYesThe buyout amount to charge
effectiveDateNoWhen ownership transfers (default: today)
reasonNoReason for buyout

Example Request

{
  "buyoutPrice": 450.00,
  "reason": "Customer requested purchase at contract end"
}

What Happens

When you process a buyout:
  1. Subscription status changes to ended_buyout
  2. Asset ownership transferred to customer
  3. Asset status changed to sold or unavailable
  4. Buyout details recorded on subscription
  5. Future payments cancelled
  6. Final invoice generated for buyout amount

Response Structure

{
  "success": true,
  "message": "Buyout processed successfully",
  "subscription": {
    "subscriptionId": "sub_abc123",
    "status": "ended_buyout",
    "buyoutDetails": {
      "buyoutDate": "2025-01-20",
      "buyoutPrice": 450.00,
      "remainingMonths": 6,
      "costRecoveryAtBuyout": 95.5
    }
  }
}

Buyout Workflow

1. Customer requests buyout
2. Calculate buyout price → /calculate-buyout
3. Present price to customer
4. Customer agrees and pays
5. Process buyout → /buyout
6. Send ownership confirmation
7. Update asset records

Example: End-to-End Buyout

async function processBuyout(subscriptionId) {
  // 1. Calculate buyout price
  const quote = await calculateBuyout(subscriptionId);

  // 2. Present to customer (in your UI)
  console.log(`Buyout price: €${quote.buyoutPrice}`);

  // 3. After customer payment confirmed, process buyout
  const result = await buyoutSubscription(subscriptionId, {
    buyoutPrice: quote.buyoutPrice,
    reason: 'Customer purchase request'
  });

  return result;
}

Buyout vs Early Return

AspectBuyoutEarly Return
DeviceCustomer keepsDevice returned
PaymentBuyout priceEarly return fee
AssetRemoved from inventoryReturns to inventory
Best forCustomer wants ownershipCustomer done with device

Error Handling

Error CodeCauseSolution
SUBSCRIPTION_NOT_ACTIVESubscription is not activeCan only buyout active subscriptions
INVALID_BUYOUT_PRICEBuyout price must be positiveProvide valid price

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
reason
enum<string>
required
Available options:
customer_request,
end_of_contract,
other
buyoutPrice
number
Required range: x >= 0
notes
string

Response

Buyout completed

success
boolean
required
rentalId
string
required
assetSerialNumber
string
required
buyoutPrice
number
required
Required range: x >= 0
currency
string
required
effectiveDate
string
required
message
string
required