Subscriptions sold by a reseller must be managed as described here.
In this document:
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.
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.
A subscription lifecycle typically includes the following operations considered in this document:
Retrieve Subscriptions: use this when you need to determine what subscriptions the reseller sold and must serve currently.
Get Subscription Details: estimate limits and usage of the subscription resources.
Upgrade or Downgrade Subscriptions: upgrade resource limits.
Switch Subscription for another Product or another Period: switch the subscription to another service.
Renew Subscription Period: keep the subscription alive for the next period.
Hold and Release Subscription: manage the subscription status.
Cancel Subscription: in many cases, this is the final operation with a subscription.
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.
Subscriptions are available on the APS bus as APS resources based on the BSSSubscription APS type.
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.
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"
}
]
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"
}
Note
In terms of billing, an operation causes a subscription downgrade if the operation refund exceeds the fee for the update.
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.
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"
}
}
]
}
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.
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:
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.
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.
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.
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.
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.
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"
}
]
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.
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.
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:
BSSSubscription APS type
OrderManagementApplication APS type
Other informal documents on using API to manage resources of the platform and integrated applications are:
Manage Orders demonstrates the API for managing all types of orders
Manage Subscriptions demonstrates the API for managing subscriptions