Skip to main content
POST
/
v1
/
subscriptions
Create a subscription
curl --request POST \
  --url https://api-eu.flexportal.io/v1/subscriptions \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Tenant-ID: <tenant-id>' \
  --data '
{
  "orderId": "ord_abc123xyz",
  "orderItemIndex": 0,
  "serialNumber": "C02ZN1ABCD12",
  "billingStartOption": "immediate"
}
'
{
  "success": true,
  "message": "<string>",
  "rentalId": "<string>",
  "rental": {
    "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>"
  }
}

Overview

Create a new subscription to fulfill an order item. This is the key step that activates a customer’s subscription—it assigns a physical asset (by serial number) to an order line item and starts the billing cycle.
You must have a confirmed order before creating subscriptions. Subscriptions are created for each unit in an order—a line item with quantity 3 requires 3 separate subscription create calls.

The Fulfillment Flow

1. Order created (status: pending)
2. Order confirmed (status: confirmed)
3. Create subscription for each item ← This endpoint
4. Order fulfilled (status: fulfilled) when all items have subscriptions

Common Use Cases

Order Fulfillment

Activate subscriptions as devices are shipped to customers

Warehouse Integration

Automatically create subscriptions when assets are scanned for shipping

Bulk Activation

Fulfill multiple-unit orders by creating subscriptions for each item

Migration

Import existing subscriptions when migrating from another platform

Request Fields

FieldRequiredDescription
orderIdYesThe order to fulfill
assetSerialNumberYesSerial number of the asset to assign
customerIdYesCustomer ID for this subscription
billingGroupIdNoBilling group for consolidated B2B invoicing
startDateNoSubscription start date (default: today)
contractLengthNoContract duration in months (1-120, default: from order)
notesNoInternal notes for this subscription

Basic Example

{
  "orderId": "ord_abc123",
  "assetSerialNumber": "SN123456789",
  "customerId": "cust_xyz789"
}

Example with Custom Start Date

{
  "orderId": "ord_abc123",
  "assetSerialNumber": "SN123456789",
  "customerId": "cust_xyz789",
  "startDate": "2025-02-01"
}
Use a future start date when shipping devices—the subscription (and billing) starts when the customer receives the device, not when you create the record.

Fulfilling Multi-Unit Orders

For an order with 3 units of the same product:
const order = await getOrder('ord_abc123');
const item = order.items[0]; // First line item

// Get available assets for this SKU
const { assets } = await listAssets({
  sku: item.sku,
  status: 'available',
  limit: item.quantity
});

// Create subscription for each unit
for (const asset of assets) {
  await createSubscription({
    orderId: order.orderId,
    assetSerialNumber: asset.serialNumber,
    customerId: order.customerId
  });
}

Asset Requirements

The serial number must reference an asset that:
  1. Exists in your asset inventory
  2. Matches the SKU from the order item
  3. Is available (status: available)
After subscription creation, the asset status changes to rented_out.

What Gets Created

When you create a subscription:
  1. Subscription record created with billing schedule
  2. Asset status updated to rented_out
  3. Order progress updated (rentedDevices count)
  4. First payment scheduled based on tenant settings
  5. Customer record updated with new device count

Billing Start Options

Your tenant settings control when billing starts:
SettingBehavior
immediateFirst payment due immediately
first_of_next_monthFirst payment on 1st of next month
same_day_next_monthFirst payment same day next month

Error Handling

Error CodeCauseSolution
ORDER_NOT_FOUNDInvalid order IDVerify order exists
ORDER_NOT_CONFIRMEDOrder not in confirmed statusConfirm order first
ITEM_FULLY_FULFILLEDAll units for this item already have subscriptionsCheck order item quantity
ASSET_NOT_FOUNDSerial number doesn’t existCreate asset first
ASSET_NOT_AVAILABLEAsset already rented or unavailableUse a different asset
SKU_MISMATCHAsset SKU doesn’t match order itemVerify correct asset

Authorizations

Authorization
string
header
required

API key obtained from FlexPortal dashboard

Headers

Tenant-ID
string
required

Your tenant identifier

Body

application/json
orderId
string
required
Minimum string length: 1
assetSerialNumber
string
required
Minimum string length: 1
customerId
string
required
Minimum string length: 1
billingGroupId
string
startDate
string<date-time>
contractLength
integer
Required range: 1 < x <= 120
notes
string

Response

Subscription created

success
enum<boolean>
required
Available options:
true,
false
message
string
required
rentalId
string
required
rental
object
required