Skip to main content
POST
/
v1
/
subscriptions
/
{subscriptionId}
/
replace
Replace subscription device
curl --request POST \
  --url https://api-eu.flexportal.io/v1/subscriptions/{subscriptionId}/replace \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Tenant-ID: <tenant-id>' \
  --data '
{
  "rentalId": "<string>",
  "newSerialNumber": "<string>",
  "replacementReason": "damaged",
  "newSku": "<string>",
  "damageAssessment": "<string>",
  "insuranceClaim": false,
  "notes": "<string>"
}
'
{
  "success": true,
  "message": "<string>",
  "rentalId": "<string>",
  "oldSerialNumber": "<string>",
  "newSerialNumber": "<string>",
  "reason": "<string>"
}

Overview

Replace a faulty or damaged device with a new one of the same type. Unlike upgrades, replacements keep the same subscription terms—the customer gets a working device without changing their contract.

When to Use Replacements

ScenarioUse This
Device is malfunctioningReplace
Device was damagedReplace
Customer wants newer modelUpgrade
Customer wants to extend contractExtend

Request Fields

FieldRequiredDescription
newSerialNumberYesSerial number of replacement device
reasonYesReason for replacement

Example Request

{
  "newSerialNumber": "SN987654321",
  "reason": "Battery failure - device won't hold charge"
}

What Happens

When you replace a device:
  1. Previous asset status changed to unavailable
  2. New asset linked to subscription and marked rented_out
  3. Replacement history logged with both serial numbers
  4. Contract terms remain unchanged
  5. Billing continues uninterrupted

Replacement vs Upgrade

AspectReplaceUpgrade
DeviceSame modelDifferent/better model
ContractUnchangedNew contract
Monthly priceSameMay change
Typical reasonFault/damageCustomer request
LogisticsSame type swapDifferent device

Asset Requirements

The replacement serial number must:
  1. Exist in your asset inventory
  2. Match the same SKU as the original (same product type)
  3. Be available (status: available)

Replacement History

After replacement, the subscription tracks all swaps:
{
  "replacementHistory": [
    {
      "replacedAt": "2025-01-20T14:30:00Z",
      "previousSerialNumber": "SN123456789",
      "newSerialNumber": "SN987654321",
      "reason": "Battery failure - device won't hold charge"
    }
  ],
  "currentSerialNumber": "SN987654321"
}

Example: Device Replacement Workflow

async function replaceDevice(subscriptionId, reason) {
  // 1. Get subscription to find SKU
  const subscription = await getSubscription(subscriptionId);

  // 2. Find available replacement of same type
  const { assets } = await listAssets({
    sku: subscription.sku,
    status: 'available',
    limit: 1
  });

  if (assets.length === 0) {
    throw new Error(`No available ${subscription.sku} in inventory`);
  }

  // 3. Process replacement
  const result = await replaceSubscriptionDevice(subscriptionId, {
    newSerialNumber: assets[0].serialNumber,
    reason
  });

  // 4. Schedule return pickup for faulty device
  await scheduleReturnPickup(subscription.serialNumber, subscription.customerId);

  return result;
}

Common Replacement Reasons

Document the reason clearly for tracking and warranty purposes:
  • Battery failure
  • Screen damage
  • Keyboard malfunction
  • Performance issues
  • Physical damage (specify type)
  • Manufacturing defect

Error Handling

Error CodeCauseSolution
SUBSCRIPTION_NOT_ACTIVESubscription is not activeCan only replace on active subscriptions
ASSET_NOT_FOUNDReplacement serial doesn’t existCreate asset first
ASSET_NOT_AVAILABLEReplacement asset not availableUse different asset
SKU_MISMATCHReplacement doesn’t match original productUse same product type

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
newSerialNumber
string
required
Minimum string length: 1
replacementReason
enum<string>
required
Available options:
damaged,
stolen,
defective,
lost
newSku
string
damageAssessment
string
insuranceClaim
boolean
default:false
notes
string

Response

Device replaced

success
enum<boolean>
required
Available options:
true,
false
message
string
required
rentalId
string
required
oldSerialNumber
string
required
newSerialNumber
string
required
reason
string
required