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

Overview

Cancel an active subscription. Use this when a customer wants to terminate their subscription without going through the normal end-of-contract flow. Unlike early return, cancellation doesn’t immediately trigger a device return.

When to Use Cancellation

ScenarioUse This
Customer requests terminationCancel
Repeated payment failuresCancel
Fraud detectedCancel
Customer wants device back immediatelyEarly Return
Customer wants to purchase deviceBuyout

Request Fields

FieldRequiredDescription
rentalIdYesThe subscription ID to cancel
reasonYesCancellation reason (see options below)
notesNoAdditional notes (max 1000 chars)

Reason Options

ReasonWhen to Use
customer_requestCustomer asked to end subscription
payment_failureRepeated failed payment attempts
fraudFraudulent activity detected
admin_decisionInternal business decision
otherOther reasons (specify in notes)

Example Request

{
  "rentalId": "sub_abc123",
  "reason": "customer_request",
  "notes": "Customer relocating internationally"
}

What Happens

When you cancel a subscription:
  1. Subscription status changes to cancelled
  2. Future payments are voided
  3. Asset marked for return collection
  4. Cancellation logged with reason and timestamp

Response Fields

FieldDescription
successAlways true on success
rentalIdThe cancelled subscription ID
assetSerialNumberSerial number of device to collect

Example: Cancel with Payment Failure

async function cancelForNonPayment(subscriptionId, failedAttempts) {
  const subscription = await getSubscription(subscriptionId);

  return await cancelSubscription(subscriptionId, {
    rentalId: subscriptionId,
    reason: 'payment_failure',
    notes: `Cancelled after ${failedAttempts} failed payment attempts`
  });
}

Example: Customer-Initiated Cancellation

async function processCancellationRequest(subscriptionId, customerReason) {
  // Log the cancellation
  await cancelSubscription(subscriptionId, {
    rentalId: subscriptionId,
    reason: 'customer_request',
    notes: customerReason
  });

  // Schedule device collection
  const subscription = await getSubscription(subscriptionId);
  await scheduleCollection(subscription.assetSerialNumber, subscription.customerId);
}

Cancellation vs Early Return

AspectCancelEarly Return
Primary useAdministrative terminationCustomer-initiated return
Device returnScheduled separatelyImmediate return expected
FeesNo automatic feeMay include early return fee
Typical scenariosPayment issues, fraudCustomer doesn’t want device

Error Handling

Error CodeCauseSolution
NOT_FOUNDSubscription doesn’t existVerify subscription ID
ALREADY_CANCELLEDSubscription already cancelledNo action needed
ALREADY_ENDEDSubscription already endedCannot cancel completed subscriptions

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,
payment_failure,
fraud,
admin_decision,
other
notes
string
Maximum string length: 1000

Response

Subscription cancelled

success
enum<boolean>
required
Available options:
true,
false
rentalId
string
required
assetSerialNumber
string
required
previousStatus
enum<string>
required
Available options:
active
cancelledAt
string
required
message
string
required