Subscription Management

Subscriptions sold by a reseller must be managed as described here.

Note

To manage subscriptions as explained below, an external system must be granted the right to call custom operations exposed by the http://www.odin.com/billing/Subscription APS type with both GET and POST methods.

Order Types

Any changes of a subscription through API should be done by placing a certain type of order as demonstrated in this document. The order management operations are exposed by the OrderManagementApplication APS type.

As explained in the previous Reselling Products document, to get a list of orders, use the following request:

GET /aps/2/services/order-manager/orders

The external system will use this call periodically to check the status of the placed orders.

Subscription Lifecycle

A subscription lifecycle typically includes the following operations considered in this document:

Note

The APS-Actor-Scope: FULL header is required to retrieve the subscriptions of all subsidiary accounts. By default, only the reseller’s own subscriptions will show up.

Retrieve Subscriptions

Subscriptions are available on the APS bus as APS resources based on the BSSSubscription APS type.

Get All Subscriptions

The following is a simple request to retrieve all subscriptions: the reseller’s own subscription that keeps the reseller status alive and subscriptions owned by all its sub-resellers and customers:

GET /aps/2/collections/subscriptions

"APS-Actor-Scope": "FULL"

The response will contain not only the subscriptions created for customers but also the reseller’s own subscriptions.

Exclude Own Subscriptions from the List

To exclude the reseller’s own subscriptions from the list, the external system must apply an RQL filter that excludes the subscription owned by the account whose APS ID is the ID of the reseller as in the following example:

GET aps/2/collections/bss-subscriptions?ne(account.aps.id,78ee642d-3b8a-48f1-af12-90563e38bd18)

"APS-Actor-Scope": "FULL"

HTTP/1.1 200 OK

[
   {
      "subscriptionPeriod": {
         "duration": 1,
         "unit": "MONTHS"
      },
      "aps": {
         "modified": "2019-03-15T18:40:33Z",
         "id": "9a907085-58a0-41c8-88b2-f9b12feaaadb",
         "type": "http://www.odin.com/billing/Subscription/1.0",
         "status": "aps:ready",
         "revision": 1
      },
      "serviceStatus": "NOT_EXIST",
      "billingTerms": {
         "billingPeriod": {
            "duration": 1,
            "unit": "MONTHS"
         },
         "billingModel": "CHARGE_BEFORE_BILLING_PERIOD",
         "freezePrices": false,
         "autoRenewal": {
            "type": "DISABLED"
         }
      },
      "name": "User Management Demo",
      "serviceGate": "PEMGATE",
      "subscriptionId": 1000004,
      "autoRenewEnabled": false,
      "trial": false,
      "status": "NEW"
   }
]

Get Subscription Details

On the APS bus, the subscriptions are represented by APS resources instantiated from the BSSSubscription APS type. In that APS type definition, you will find subscription properties, the links to other APS resources, and custom operations that allow the external system to get necessary details about a particular subscription as demonstrated in the following sections.

To retrieve properties and relationship with other APS resources of a subscription, send a GET request referring to the subscription by its APS ID, for example:

GET /aps/2/resources/9a907085-58a0-41c8-88b2-f9b12feaaadb

"APS-Actor-Scope": "FULL"

The response contains the subscription general properties and the links to other APS resources:

 HTTP/1.1 200 OK

 {
    "aps": {
       "schema": "/aps/2/types/156",
       "package": {
          "id": "92ccf5e8-fc07-4e7f-8875-5c19c8545870",
          "href": "/aps/2/packages/92ccf5e8-fc07-4e7f-8875-5c19c8545870"
       },
       "modified": "2019-03-15T18:40:33Z",
       "id": "9a907085-58a0-41c8-88b2-f9b12feaaadb",
       "type": "http://www.odin.com/billing/Subscription/1.0",
       "status": "aps:ready",
       "revision": 1
    },
    "subscriptionPeriod": {
        "duration": 1,
        "unit": "MONTHS"
    },
    "account": {
       "aps": {
          "link": "weak",
          "href": "/aps/2/resources/26ae28d2-0303-4189-8e1d-02796ee5de3b",
          "id": "26ae28d2-0303-4189-8e1d-02796ee5de3b"
       }
    },
    "billingTerms": {
       "billingPeriod": {
          "duration": 1,
          "unit": "MONTHS"
       },
       "freezePrices": false,
       "billingModel": "CHARGE_BEFORE_BILLING_PERIOD",
       "autoRenewal": {
          "type": "DISABLED"
       }
    },
    "servicePlan": {
       "aps": {
          "link": "weak",
          "href": "/aps/2/resources/51615892-655d-409d-a922-4423a8188b2e",
          "id": "51615892-655d-409d-a922-4423a8188b2e"
       }
    },
    "bssAccountInfo": {
       "aps": {
          "link": "weak",
          "href": "/aps/2/resources/424eef0c-d847-11e8-8a73-60fb42f13c76",
          "id": "424eef0c-d847-11e8-8a73-60fb42f13c76"
       }
    },
    "childSubscriptions": {
       "aps": {
          "link": "collection",
          "href": "/aps/2/resources/9a907085-58a0-41c8-88b2-f9b12feaaadb/childSubscriptions"
       }
    },
    "name": "User Management Demo",
    "serviceGate": "PEMGATE",
    "subscriptionId": 1000004,
    "serviceStatus": "NOT_EXIST",
    "trial": false,
    "vendor": {
       "aps": {
          "link": "weak",
          "href": "/aps/2/resources/78ee642d-3b8a-48f1-af12-90563e38bd18",
          "id": "78ee642d-3b8a-48f1-af12-90563e38bd18"
       }
    },
    "autoRenewEnabled": false,
    "status": "NEW"
}

Upgrade or Downgrade Subscriptions

Note

In terms of billing, an operation causes a subscription downgrade if the operation refund exceeds the fee for the update.

Get List of Resources

Before upgrading or downgrading, get a list of resources that show the limit and usage for each resource in the subscription by calling the getResources operation exposed by the BSSSubscription APS type.

GET /aps/2/resources/9a907085-58a0-41c8-88b2-f9b12feaaadb/resources

The response contains a list of subscription resources:

HTTP/1.1 200 OK

[
   {
      "resourceId": "098a7165-8666-4f8d-8037-e34665e664e4",
      "internalResourceId": 1000070,
      "status": "PURCHASED",
      "name": {
         "en_US": "User Management Demo - VPS Mainstream Profile"
      },
      "unitOfMeasureId": "unit",
      "unitOfMeasure": {
         "en_US": "unit"
      },
      "measurable": false,
      "showInCustomerPanel": true,
      "allowToModifyInTrial": false,
      "included": "1.0",
      "additional": "0.0",
      "ordered": "1.0",
      "min": "1.0"
   },
   {
      "resourceId": "2a27b06b-b18e-4609-87ca-5a21e961c143",
      "internalResourceId": 1000071,
      "status": "PURCHASED",
      "name": {
         "en_US": "User Management Demo - VPS Premium Profile"
      },
      "unitOfMeasureId": "unit",
      "unitOfMeasure": {
         "en_US": "unit"
      },
      "measurable": false,
      "showInCustomerPanel": true,
      "allowToModifyInTrial": false,
      "included": "0.0",
      "additional": "0.0",
      "ordered": "0.0",
      "min": "0.0"
   }
]

Pay attention to the resources that must be upgraded by the next operation: the two resources whose platform internal IDs are 1000070 and 1000071 in the above response.

Resource Upgrade Estimation

Before starting the upgrade process, estimate its price by sending an order estimation request that contains the resources and the new desired resource amount:

POST /aps/2/services/order-manager/orders/estimate

"APS-Actor-Scope": "FULL"

{
   "type": "CHANGE",
   "subscriptionId": "9a907085-58a0-41c8-88b2-f9b12feaaadb",
   "paymentMethodId": "12",
   "resources": [
      {
         "resourceId": "098a7165-8666-4f8d-8037-e34665e664e4",
         "amount": 10
      },
      {
         "resourceId": "2a27b06b-b18e-4609-87ca-5a21e961c143",
         "amount": 5
      }
   ]
}

The response shows the price estimation in total and with details:

HTTP/1.1 200 OK

{
  "total": {
    "value": "15.62",
    "code": "USD"
  },
  "subTotal": {
    "value": "13.95",
    "code": "USD"
  },
  "taxTotal": {
    "value": "1.67",
    "code": "USD"
  },
  "exclusiveTaxTotal": {
    "value": "1.67",
    "code": "USD"
  },
  "details": [
    {
      "type": "RESOURCE_RECURRING",
      "planId": "51615892-655d-409d-a922-4423a8188b2e",
      "period": {
        "unit": "MONTHS",
        "duration": 1
      },
      "resourceId": "098a7165-8666-4f8d-8037-e34665e664e4",
      "duration": {
        "unit": "MONTHS",
        "duration": "1.0"
      },
      "description": "User Management Demo - VPS Mainstream Profile Recurring",
      "quantity": "8.0",
      "lowerBound": "0.0",
      "unitOfMeasure": "unit",
      "unitPrice": {
        "value": "1.0",
        "code": "USD"
      },
      "extendedPrice": {
        "value": "7.2",
        "code": "USD"
      },
      "discount": {
        "type": "PERCENT",
        "value": "10.0",
        "amount": "0.8"
      },
      "taxAmount": {
        "value": "0.86",
        "code": "USD"
      },
      "exclusiveTaxAmount": {
        "value": "0.86",
        "code": "USD"
      }
    },
    {
      "type": "RESOURCE_RECURRING",
      "planId": "51615892-655d-409d-a922-4423a8188b2e",
      "period": {
        "unit": "MONTHS",
        "duration": 1
      },
      "resourceId": "2a27b06b-b18e-4609-87ca-5a21e961c143",
      "duration": {
        "unit": "MONTHS",
        "duration": "1.0"
      },
      "description": "User Management Demo - VPS Premium Profile Recurring",
      "quantity": "5.0",
      "lowerBound": "0.0",
      "unitOfMeasure": "unit",
      "unitPrice": {
        "value": "1.5",
        "code": "USD"
      },
      "extendedPrice": {
        "value": "6.75",
        "code": "USD"
      },
      "discount": {
        "type": "PERCENT",
        "value": "10.0",
        "amount": "0.75"
      },
      "taxAmount": {
        "value": "0.81",
        "code": "USD"
      },
      "exclusiveTaxAmount": {
        "value": "0.81",
        "code": "USD"
      }
    }
  ]
}

Upgrade Subscription Resources

To buy a larger amount of the resources estimated in the previous request, create a change order with the same parameters as those used in the estimation request:

POST /aps/2/services/order-manager/orders

"APS-Actor-Scope": "FULL"

{
   "type": "CHANGE",
   "subscriptionId": "9a907085-58a0-41c8-88b2-f9b12feaaadb",
   "paymentMethodId": "12",
   "resources": [
      {
         "resourceId": "098a7165-8666-4f8d-8037-e34665e664e4",
         "amount": 10
      },
      {
         "resourceId": "2a27b06b-b18e-4609-87ca-5a21e961c143",
         "amount": 5
      }
   ]
}

The above request will upgrade the resource limits in the subscription: the first resource from 2 to 10 items and the second resource from 0 to 5 items.

A response shows the ID of the created change order:

HTTP/1.1 200 OK

{"orderId":"0cf600ba-38f8-495f-8502-a075e4297226"}

The external system can check the order status and the subscription resources to ensure the requested update is completed as expected.

Switch Subscription for another Product or another Period

It is possible to switch a subscription to another service plan or change only the subscription period within the same service plan. In either case, it requires a similar API call, in which the APS ID of the targeted service plan and subscription period length are required.

When switching to a longer subscription period, there may be a downgrade operation, because, a billing period (1 month in both cases) usually costs less within a longer subscription period.

Note

If the requested switching to a new period requires a subscription downgrade the change order will not be processed automatically and will wait for manual processing in the reseller control panel.

To switch the subscription from the current 1 month period to the 3 month period, place a change order with the following content:

POST /aps/2/services/order-manager/orders

"APS-Actor-Scope": "FULL"

{
   "type": "CHANGE",
   "subscriptionId": "9a907085-58a0-41c8-88b2-f9b12feaaadb",
   "planId": "51615892-655d-409d-a922-4423a8188b2e",
   "paymentMethodId": "12",
   "period": {
      "unit": "MONTHS",
      "duration": 3
   },
   "resources": [
      {
         "resourceId": "2a27b06b-b18e-4609-87ca-5a21e961c143",
         "amount": 10
      },
      {
         "resourceId": "098a7165-8666-4f8d-8037-e34665e664e4",
         "amount": 15
      }
   ]
}

The above change order also contains a request for resource upgrade. A response will show the ID of the created change order:

HTTP/1.1 200 OK

{"orderId":"604d0e33-a6fc-47af-b9a3-48e51e7ab61d"}

If the external system requests a list of orders, the new change order that requires downgrading will look as follows (for the illustration, below is a change order different from the one generated by the last request):

{
   "orderId": "84676a25-3586-45be-9862-c4b7ed999365",
   "orderNumber": "CH000004",
   "type": "CH",
   "status": "NOT_STARTED",
   "paymentStatus": "AVAILABLE",
   "provisioningStatus": "NOT_STARTED",
   "ofStatus": "NW",
   "sellerId": "0bc94a14-f508-474d-bd5d-bed53ea0397f",
   "buyerId": "43a44c26-e218-4247-89ea-e0e45d329c02",
   "orderDate": "2018-10-28T21:00:00Z",
   "expirationDate": "2018-11-27T21:00:00Z",
   "creationTime": "2018-10-29T09:39:46Z"
}

In the above response, even though the payment status is available, the order processing was not started as the downgrade requires the attention of the reseller. To start the order processing, the reseller must open the order in the reseller control panel and click the Open Order button:

../../../_images/change-order-open-required.png

Renew Subscription Period

If the Auto-renewal property in the service plan is enabled, the platform will renew the subscription automatically for the next subscription period, when the subscription is coming up to its expiration date. Alternatively, the reseller’s external system can do it by creating a renewal order as in the following example:

POST /aps/2/services/order-manager/orders

"APS-Actor-Scope": "FULL"

{
   "type": "RENEWAL",
   "subscriptionId": "9a907085-58a0-41c8-88b2-f9b12feaaadb",
   "paymentMethodId": "12",
   "period": {
      "unit": "MONTHS",
      "duration": 3
   }
}

As usual, when the external system places an order, the order ID will show up in the response:

HTTP/1.1 200 OK

{"orderId":"1875071d-68b8-4b3c-88a8-98ef52d33500"}

The external system can check the order status to ensure the requested update is completed as expected.

Hold and Release Subscription

For some commercial or other reasons, the reseller can put a subscription on hold and then release it after some period. Those operations can be done automatically by the platform, manually in the user panel, or by calling the special custom operations exposed by the OrderManagementApplication APS type.

Put on Hold

To put a subscription on the administrative hold, the external system must call the putOnHold operation as in the following example:

POST /aps/2/resources/9a907085-58a0-41c8-88b2-f9b12feaaadb/putOnHold

{
   "reason": "ACCOUNT_OVERDUE",
   "comment": "Requested by the ERP system."
}

Response:

HTTP/1.1 204 OK

The response does not contain a payload.

Release from Hold

To release a subscription from the hold status, the external system must call the releaseFromHold operation as in the following example:

POST /aps/2/resources/73e5f324-185f-4495-bc45-e50adfac472d/releaseFromHold

{
  "reason": "OTHER",
  "comment": "The balance was restored. Requested by the ERP system."
}

Response:

HTTP/1.1 204 OK

The response does not contain a payload.

Cancel Subscription

In some circumstances, a customer or the reseller may cancel a subscription. For that purpose, the external system can request the creation of a cancellation order that, in its turn, will require the platform to cancel the subscription.

Get Cancellation Reasons

The external system can specify a reason for cancelling a subscription. For this purpose, it must be aware which reasons are allowed by the platform. To get a list of all possible reasons, the request must be as follows:

GET /aps/2/services/order-manager/reasonCodes

To select the reasons by operation type, add the appropriate filter as in the following example:

GET /aps/2/services/order-manager/reasonCodes?operationType=CANCEL_BY_VENDOR

The response to the last request will show the list of reasons that can be used by the sales vendor, that is by the reseller:

HTTP/1.1 200 OK

[
  {
    "reasonId": 13,
    "description": {
      "en_US": "Customer Request"
    },
    "operationType": "CANCEL_BY_VENDOR"
  },
  {
    "reasonId": 14,
    "description": {
      "en_US": "Other"
    },
    "operationType": "CANCEL_BY_VENDOR"
  }
]

Use Cancellation Requests with Reasons

A request to cancel a subscription for a specific reason must be as follows:

POST /aps/2/services/order-manager/orders

{
   "type": "CANCELLATION",
   "refundType":"CREDIT_MEMO",
   "subscriptionId" : "a63078fb-7af8-417e-88c3-e7af37e08e59",
   "reasonId": 14,
   "comment": "Requested through the ERP system."
}

This is a typical response that shows the order ID:

HTTP/1.1 200 OK

{
   "orderId": "27a94b1e-28b7-4bbd-a30d-ff4c44005d56"
}

The body contains the cancellation order ID.

If the customer must be paid for the unused period of time, whether by creating a credit memo or by refund, the new cancellation order will be in the “New” status waiting for further action.

Note

If the cancellation order is in the New status, the cancellation order process must be kicked off by the reseller manually in the reseller control panel or by calling the API push custom operation as explained later in this document. Until this is done, although the subscription services are stopped for the customer, the subscription status is still active.

../../../_images/subscription-cancellation.png

Push Cancellation Order Processing

If a cancellation order is stuck in the “New” status, the ofStatus (order flow status) property returned by the order details request, will be NW.

To continue the normal order processing and make it “completed”, the external system must open the order by sending a push request for the order to transition to the OP (Open) status as in the following example:

POST /aps/2/services/order-manager/orders/4449abb3-f760-4bd8-98cc-c8e36352c3a7/push

{
   "ofStatus": "OP"
}

If successful, the response only contains the header HTTP/1.1 200 OK (without body). If you request the order details, the returned order flow status will be "ofStatus":"CP" (“Completed”). The respective subscription is now terminated.

Conclusion

In this subscription management scenario, you went through the typical steps in a subscription lifecycle. The API used here is presented in detail in these formal API Reference documents:

Other informal documents on using API to manage resources of the platform and integrated applications are: