General licensing workflow
This document describes:
- how licenses that are bound to a machine can be created,
- how to retrieve created licenses and
- how the license can be used to assign the machine to an application, so the customer can use it.
For the different steps of the process, different access rights are needed. To manage licenses, the calling api client needs to act in scope of a developer subscription. In order to assign machines to applications, the calling api client needs to act as the manufacturer of the machine.
If your company has separate manufacturer and developer subscriptions, you will need to use different clients to execute all the steps in this workflow.
Managing licenses for machines
This section describes how to create licenses which are bound to a machine. Such a license will grant the rights to use an application to the current owner(s) of its machine. In other words, if a customer onboards the machine in his subscription, he will be granted the rights to use the license. If he removes the machine, e.g. because it is sold, the license will be automatically revoked and transferred to the new owner.
Create a license
In order to create a license, you first need to obtain the id of the application for which you want to create the license. This application id is provided by tapio when an application is created in a developer subscription. Second, you need the tapioMachineId of the machine to which the license should be bound.
Each license is unique per application and machine. Consequently, you cannot issue multiple licenses for the same application to a single machine.
Although ownership of a license can be bound to a specific machine, the usage for the customer can not. This means the customer is free to assign the license to any machine. To ensure that a certain machine is actually assigned to a specific machine refer to access assigned machines.
To create the license use the following route:
POST
https://api.tapio.one/management/applications/{targetApplicationId}/machines/{tapioMachineId}/license
Parameters
Property | Location | Description | Datatype | Required |
---|---|---|---|---|
targetApplicationId | Route | Id of the application for which the license will be created | Guid | Yes |
tapioMachineId | Route | Id of the machine to which the license will be bound | string | Yes |
Request body
{
"data": {
"name": "Example license", // Name of your license (required).
"issuedAt": "2020-04-03T00:00:00", // Time the license was issued (required).
"machineCount": 1, // Number of machines, that can be assigned to this license (usually 1) (required).
"serialNumber": "serial.myapp.2345", // Your serial number (required).
"validFrom": "2020-04-03T00:00:00", // Start time of your license (required).
"validTo": "2021-03-30T00:00:00" // Expiry date of your license (required).
}
}
Response model
201 - Created.
{
"id": "c91d01ba-b4b8-4510-99d6-0c984f26420e" // The id of the created object.
}
Retrieve a license
After creating a license, it can be retrieved using the unique combination of applicationId and tapioMachineId.
GET
https://api.tapio.one/management/applications/{targetApplicationId}/machines/{tapioMachineId}/license
Property | Location | Description | Datatype | Required |
---|---|---|---|---|
targetApplicationId | Route | Id of the application for which to retrieve the license | Guid | Yes |
tapioMachineId | Route | Id machine for which to retrieve the license | string | Yes |
Response Model
200 - Ok
404 - NotFound.
{
"id": "c91d01ba-b4b8-4510-99d6-0c984f26420e", // id of the license
"createdAt": "2020-05-11T14:58:48.3777842+00:00", // creation date
"tapioMachineId": "ma1234567890", // id of the machine
"applicationId": "b19fbf71-7c32-4a51-aab5-c1bc3b3eb5b7", // targetApplicationId
"data": {
"name": "Example license", // Name of your license
"issuedAt": "2020-04-03T00:00:00", // Time the license was issued
"machineCount": 1, // Number of machines, that can be assigned to this license.
"serialNumber": "serial.myapp.2345", // Your serial number.
"validFrom": "2020-04-03T00:00:00", // Start time of your license
"validTo": "2021-03-30T00:00:00" // Expiry date of your license
}
}
Retrieve all licenses for an application
Using the route below, it is also possible to retrieve all the licenses that have been issued for a specific application.
GET
https://api.tapio.one/management/applications/{targetApplicationId}/machines/licenses?continuationToken={continuationToken}
Property | Location | Description | Datatype | Required |
---|---|---|---|---|
targetApplicationId | Route | Id of the application for which to retrieve the licenses | Guid | Yes |
continuationToken | Query | ContinuationToken to request a specific page. If null or empty, the first page is retrieved. | string | No |
The route uses continuation tokens for server-side paging. In order to access the next page of the result, clients have to provide the continuation token that has been returned by the previous response. To access the first page use an empty or null token. The continuationToken must be URL-encoded. Finally, if the server returns an empty token there are no further pages.
Response Model
200 - Ok
{
"items": [
{
"id": "c91d01ba-b4b8-4510-99d6-0c984f26420e", // id of the license
"createdAt": "2020-05-11T14:58:48.3777842+00:00", // creation date
"tapioMachineId": "ma1234567890", // id of the machine
"applicationId": "b19fbf71-7c32-4a51-aab5-c1bc3b3eb5b7", // targetApplicationId
"data": {
"name": "Example license", // Name of your license
"issuedAt": "2020-04-03T00:00:00", // Time the license was issued
"machineCount": 1, // Number of machines, that can be assigned to this license.
"serialNumber": "serial.myapp.2345", // Your serial number.
"validFrom": "2020-04-03T00:00:00", // Start time of your license
"validTo": "2021-03-30T00:00:00" // Expiry date of your license
}
}
],
"pagination": {
"continuationToken": "-RID:IDVQdYALe2seBzAQAAAAAAAA==", // The continuation token to access the next page. Null or empty if there are no further pages.
}
}
Managing bundle for customer
In the tapio environment there are applications. These applications like MachineBoard can be used in the tapio environment, for example to interact with machines. Therefore, you have to order a license for these applications. Often several licenses of different applications belong together and are called Bundles. This section describes how to manage bundles for a customer. Those licenses can be managed by the partner or can handover to the tapio shop, so the customer can manage them by himself.
API is asynchronous designed.
Get all bundle definitions
To create a bundle for a customer you first have to retrieve a bundle definition.
GET
https://api.tapio.one/management/bundleDefinitions?continuationToken=<continuationToken>
Property | Description | Datatype | Required |
---|---|---|---|
continuationToken | Used for pagination, in case it is empty there is no further page available. | string | no |
Response Model
{
"continuationToken": "",
"data": [
{
"id": "78ff519c-9c58-405c-a41e-6d8f5150f44e",
"displayName": "Edgeband Management Set 'Classic'",
"supportedPeriods": [
"R/P1Y" // Supported periods like R/P1Y (ISO 8601 repeating intervals)
],
"licenses": [
{
"applicationId": "60dfa00f-1245-425d-83cd-d20bd638c15b",
"displayName": "materialAssist Boards Classic",
"minimalCount": 1,
"maximumCount": null
},
{
"applicationId": "4940f484-1c04-439e-a084-18358d540725",
"displayName": "twinio",
"minimalCount": 1,
"maximumCount": null
}
],
"canBeManagedByShop": false // Can be managed by the shop so you can call the handoverToShop route
}
]
}
200 - OK.
Create bundle
To create a bundle you have to call the route with the following information. Afterwards, you have to call the Get bundle information with the returned bundle id to check the provisioning state.
POST
https://api.tapio.one/management/bundles
Request body
{
"bundleDefinitionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Id of the bundle definition you want to create an instance of (required).
"subscriptionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Subscription id of the customer (required).
"externalId": "string", // External id to have an unique identifier for the license (optional).
"licenses": [ // List of license so you can override the count of the definition. (optional).
{
"applicationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"count": 0, // The count to define how many licenses of this application should be ordered.
"comment": "string" // Comment on the license (optional).
}
],
"comment": "string" // Comment on the bundle (optional).
}
Duplication prevention is implemented via the external id. The external id has to be unique in your context. So you can use this, to avoid creating two times a bundle for a same order.
Response model
201 - Created. 400 - Bad Request. 401 - Unauthorized. 409 - Conflict. e.g. the external id is already used.
{
"id": "c91d01ba-b4b8-4510-99d6-0c984f26420e"
}
Get all Bundles
You can call this route to query all your created bundles.
GET
https://api.tapio.one/management/bundles?applicationId=<applicationId>&subscriptionId=<subscriptionId>
Property | Description | Datatype | Required |
---|---|---|---|
applicationId | Application id | Guid | no |
subscriptionId | Subscription id of the customer | Guid | no |
Response model
{
"continuationToken": "string",
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Id of the bundle
"salesChannel": { // Current sales channel
"type": "API", // Type of the channel (API, CloudBlueCommerce, Admin)
"channelId": "string", // String of the channel Id
"referenceId": "string" // String of the reference id, e.g. could be the external id
},
"bundleDefinitionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Bundle definition id
"subscriptionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Subscription id of the owner of the bundle.
"externalId": "string", // External id to have a unique identifier for these bundle
"licenses": [
{
"licenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"applicationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"count": 0, // Count of the licenses for this application
"comment": "string" // Comment of the license // (optional)
}
],
"provisioningState": "Creating", // Provisioning state of the bundle (Creating, Updating, Succeeded, Failed, Deleting, Deleted)
"bundleState": "Active", // State of the bundle (Active, Paused)
"comment": "string"
}
]
}
Get bundle information
After you created a bundle you can query the bundle and can check the state of this bundle.
GET
https://api.tapio.one/management/bundles/{bundleId}?applicationId=<applicationId>&subscriptionId=<subscriptionId>
Property | Description | Datatype | Required |
---|---|---|---|
bundleId | Bundle id | Guid | yes |
applicationId | Application id | Guid | no |
subscriptionId | Subscription id of the customer | Guid | no |
Response model
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Id of the bundle
"salesChannel": { // Current sales channel
"type": "API", // Type of the channel (API, CloudBlueCommerce, Admin)
"channelId": "string", // String of the channel Id
"referenceId": "string" // String of the reference id, e.g. could be the external id
},
"bundleDefinitionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Bundle definition id
"subscriptionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Subscription id of the owner of the bundle.
"externalId": "string", // External id to have a unique identifier for these bundle
"licenses": [
{
"licenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"applicationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"count": 0, // Count of the licenses for this application
"comment": "string" // Comment of the license // (optional)
}
],
"provisioningState": "Creating", // Provisioning state of the bundle (Creating, Updating, Succeeded, Failed, Deleting, Deleted)
"bundleState": "Active", // State of the bundle (Active, Paused)
"comment": "string"
}
Duplication prevention is implemented via the external id. The external id has to be unique in your context. So you can use this, to avoid creating two times a bundle for a same order.
ProvisioningState
display if the bundle was successful provisioned in the system. This state model get information for long-running background operations. In case the state isFailed
you have to contact the tapio support developer@tapio.one.BundleState
display the information if this bundle can be used (active) by the customer or it can not be used (paused). No costs are incurred in the paused state.
Delete bundle
After a bundle was created (bundle exist and provisioning state is Succeeded
), you also can delete it. Delete of a bundle means all containing licenses are deleted afterwards. This is possible until you called Handover the bundle to the shop. After a bundle was handed over to shop, you can no longer delete it.
DELETE
https://api.tapio.one/management/bundles/{id}?subscriptionId=<subscriptionId>
Property | Description | Datatype | Required |
---|---|---|---|
id | Bundle id | Guid | yes |
subscriptionId | Customer subscription id | Guid | no |
Response model
204 - No Content.
Handover a bundle to shop
After the bundle was created successfully (provisioning state), you can hand it over to the shop. This means the shop is responsible for the billing of the customer as well as bundle durations. The customer can also manage bundles by himself.
POST
https://api.tapio.one/management/bundles/{bundleId}/handovertoshop
Property | Description | Datatype | Required |
---|---|---|---|
bundleId | Bundle id | Guid | yes |
Request body
{
"subscriptionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Subscription of the bundle owner (required).
"period": "string", // Period of the bundle which have to match with the supportedPeriods of the bundle definition (ISO 8601 repeating intervals) (required).
"voucherCode": "string", // Voucher code (optional).
"numberOfPeriodsPaid": 0 // Number of paid periods (optional). If the customer already paid for a certain amount of periods through your offer, you have to make sure that the shop does not charge the customer too soon.
}
The system do not allow
voucherCode
andnumberOfPeriodsPaid
to be set at the same time. You can only use one of this two options. You as a partner can have you ownvoucherCode
to get a specified discount for your bundle. This voucher code has to be setup in the shop. Therfore you have contact tapio developer@tapio.one. You can use thenumberOfPeriodsPaid
to construct something like 3 times 1 year of bundleEdgeband Management Set 'Classic'
. The free times for the customer, are paid by the partner.
Response model
202 - Accepted. 400 - Bad Request. 401 - Unauthorized. 404 - Bad request. Body contains the information. 409 - Conflict e.g. a concurrent operation on this bundle, bundle already exists in shop, customer has multiple shop accounts or customer is not allowed to receive new bundles in shop.
After the handover was successfully called, you have to query the bundle by calling the Get bundle information route to check the provisioning state. The state update can take up to 1 minute. In case the state is Failed
you have to contact the tapio support developer@tapio.one. If the provisioning state is Succeeded
the handover was successful.
Get the shop expiry date of a bundle
Only works for shop-managed bundles. Gets the current shop expiry date of the bundle. After this period, the bundle will automatically renew. The customer can cancel it in the shop if the bundle is no longer required.
GET
https://api.tapio.one/management/bundles/{bundleId}/shopExpiryDate
Property | Description | Datatype | Required |
---|---|---|---|
id | bundle id | Guid | yes |
subscriptionId | customer subscription id | Guid | yes |
Response model
{
"expiryDate": "2021-10-26T00:00:00.000Z" // Expiry date as ISO 8601.
}
200 - OK.
Set the shop expiry date of a bundle
Only works for shop-managed bundles. Sets the shop expiry date of the bundle.
POST
https://api.tapio.one/management/bundles/{bundleId}/shopExpiryDate
Property | Description | Datatype | Required |
---|---|---|---|
id | bundle id | Guid | yes |
{
"subscriptionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // Subscription id of the bundle owner. (required)
"expiryDate": "2021-10-26T06:49:57.976Z" // Expiry date (relative to Coordinated Universal Time (UTC)). Must be at least 24h in the future(ISO 8601) (required). The system will just adapt the date and will ignore the concrete time.
}
Response model
200 - OK.
Accept terms of use for a specific application
After creating a license for an application, the next step is to accept the terms of use of an application on behalf of the customer. Afterwards, it is possible to assign a machine to an application.
PUT
https://api.tapio.one/management/manufacturer/customerSubscriptions/{subscriptionId}/applications/{applicationId}/termsofuse
Property | Description | Datatype | Required |
---|---|---|---|
subscriptionId | customer subscription id | Guid | yes |
applicationId | application id | Guid | yes |
Request body
{
"versionNumber": "1.0.0", // Semantic versioning. Version number needs to exist (optional).
"contractNumber": "4711", // Your contract number (required).
"acceptedLanguage": "de" // Two letter language (optional).
}
Response
201 - Created. If terms of use are accepted the first time for this application.
200 - Ok. If terms of use were already accepted.
Assign a machine to an application
After accepting the terms of use of an application, the last step is to assign the machine to the application in the customer's subscription. Afterwards, the customer is able to use it.
Important! In this step the client needs to act as the manufacturer of the machine!
PUT
https://api.tapio.one/management/manufacturer/machines/{tapioMachineId}/applicationassignment
Request body
{
"customerSubscriptionId": "aafb748b-e7ad-4b56-a45c-79a52bf4023d", // Id of the customer subscription (required).
"applicationId": "aafb1932-e7ad-4b56-a45c-79a52bf4023d" // Application to which the machine is assigned (required).
}
For a successful assignment, the machine must already exist in the customer subscription. For instructions how to onboard a machine, refer to Machine Onboarding Workflow.
Response
201 - Created. If machine is assigned to application first time.
200 - Ok. If machine is already assigned.
404 - Not found. The application assignment could not be created because there exists no free license for the specified applicationId in the specified customer subscription. Make sure that you have created a license for the machine (see Create a License) and that the machine is onboarded in the customer subscription (see Machine Onboarding Workflow).
Unassign a machine from an application
At least there is a route to unassign the machine from an application in the customer's subscription.
DELETE
https://api.tapio.one/management/manufacturer/machines/{tapioMachineId}/applicationassignment
Property | Location | Description | Datatype | Required |
---|---|---|---|---|
TapioMachineId | Route | The id of the machine in tapio ecosystem | string | Yes |
applicationId | Query | application from which the machine should unassigned | Guid | Yes |
customerSubscriptionId | Query | id of the customer subscription | Guid | Yes |
For a successful unassignment, the machine must be assigned to the application.
Response
204 - Deleted. Machine was successful unassigned from the application.
404 - NotFound. Machine is already unassigned.