Billing for Native Apps

Many of the native party apps available in BaseSpace perform processing-intensive operations that often cost BaseSpace money and will want to charge the user for the service. In order to recoup some of the costs and to encourage a thriving app ecosystem, we are providing a way for users to pay for the services provided by the apps they use.

We have expanded the BaseSpace platform with the ability for apps to charge users for the service they're receiving in a secure and simple way. BaseSpace will manage all the billing infrastructure allowing you as an app developer to focus on continuously building out your apps without worrying about the complexities of billing.

This guide has a few major sections:

General Billing Information

iCredits

All in-app purchases are performed using an Illumina currency called iCredits. Before a user can make any in-app purchases, they must add iCredits to their account by purchasing them through BaseSpace. 1 iCredit can be purchased at a rate of 1 USD.

Purchasable Products

You can configure one or more products that your application will offer for sale by going to the "Pricing" tab for your App. For each Product, you need to simply enter a description, an expiration time, and a price. Products may be purchased for a predetermined period of time, may unlock new features in the app, or may be charged based on the size of the files being analyzed. Products are very customizable, so you are free to set up your Products however you wish. Although you may change prices for your products later on, there may be some limitations for how often you may make pricing changes.

Revenue Sharing and Payouts

Payouts to app developers happen at a predetermined period, such as every 30 days, where they will get a payout in USD. The app developers get 70% of the total iCredit usage. The app developer also pays for the cost of usage (processing costs) and refunds. Illumina keeps 30% of the total usage. Illumina will not be passing on costs of usage in the initial billing rollout.

Issuing Refunds

There may be cases when your application has received iCredits but could not effectively deliver up to the user's expectations. This may be because the app encountered an error during processing, encountered or processed corrupted data, or simply because the user was unsatisfied with the results. In cases like these, we encourage apps to refund iCredits to the user.

Refunds may be provided via the API or, for native apps, automatically when the app fails. iCredits that were given to the application will then be refunded to the user. We have placed a 1 day limit on the length of time a refund may be performed from the time the purchase was made.

If the user would like a purchase to be refunded but the app provides no means for performing the refund or chooses not to, the user may contact Illumina support. Illumina has the right to decide to revoke billing rights of an application should this occur too frequently.

Supported Platforms

Billing is available for all types of apps for BaseSpace. Native, Web, Desktop, and Mobile apps all have the ability to charge the user for their services.

Keeping Track of Purchases

After selecting your App in the My App control panel, you will see the "Purchases" tab where you have access to a running log of purchases for that app. This will include purchases that were completed, cancelled, and refunded.

Avoid Redundant Purchases for Persistent Products

You can create Products that either have an expiration period or do not expire. Once the user has purchased this Product, they will not be able to purchase it again until the purchased product has expired. Currently a Persistent Product can expire after 7 days, 30 days, or never expire.

A user should not have to pay more than once for the same service, data analysis, or functionality to be made available. I

Setup and Workflow Summaries

The following section will cover the major steps required by the app in order to bill the user for the analysis.

There are three steps to set up your native app with billing:

  • Enabling Billing: Before you can begin testing out billing for the app, you must have billing enabled. To do this, please follow the instructions in this part of the guide
  • Creating Products: After having the app enabled for billing, the next step is to begin creating Products to sell in the app. This section will describe this process
  • Configuring a BillingSpec: This section will describe how to use the Formbuilder tool to configure a shopping cart for the app

In addition, to view previous purchases and manage invoices, the developer can refer to the Application Purchase History section.

Enabling Billing

Before Products or Purchases can be made, your account needs to have Billing enabled.

Every application will have Billing disabled by default. In order to see if your application has Billing enabled, simply go to the App Dashboard, click on your app, and click on the "Pricing" tab. If Billing is disabled, you will see the following:

Billing Disabled Example

To enable Billing, please send an email to basespace-apptest@illumina.com with your Application Id, Company/Organization Name, and your BaseSpace UserName/Email Address to enable billing for your application.

Creating Products

Types of Products:

  • Persistent: A Product that either has an expiration period or does not expire. Once the user has purchased this Product, they will not be able to purchase it again until the purchased product has expired. Currently a Persistent Product can expire after 7 days, 30 days, or never expire. Persistent Products can only be charged with a Quantity of 1.
  • Non-Persistent: A Product that expires immediately. A user can purchase this Product more than once. Non-Persistent Products may be charged in any Quantity.

Creating Products:

After enabling Billing for your application, you can access the "Pricing" and "Purchases" sections of the App. Simply navigate to the App Dashboard, select your app, and you will see the following tabs, highlighted in red:

App Dashboard with Billing Tabs

Click on the "Pricing" tab. After doing so, you will see the following:

Pricing Tab

Now, to create a Product, just enter the information in the "Create A New Product" section and hit the green "Create" button. If the Product was successfully added, it will be displayed in the "Current Sellable Products" table.

Note: The description of your Product should give the User detailed information about the Product being purchased. A User will see the Name and Description of the Product during the transaction as well as on the App's page on BaseSpace (see the following)

App Details Page With Pricing

In this screenshot, the Description for the Product is "RNA-Seq 7-Day Subscription" and the Price is 12 iCredits.

Configuring a BillingSpec

The next step is to begin editing the app's callbacks.js and form in the Formbuilder window to create the shopping cart to display to the user when the app is launched. This is described in detail in the Configuring the BillingSpec in the Formbuilder section below.

Application Purchase History

An Application's purchase history can be found by going to the "Purchases" tab in the App's page. The purchase history shows a list of purchases with the Purchase Id.

The following is a screenshot of the purchase history for an application:

Purchase History

Configuring the BillingSpec function in the Formbuilder

The billingSpec function is configured in much the same way as the launchSpec function for Native Apps. The billingSpec is a javascript function that will create the Shopping Cart for the user after they launch the app and configure the input form with data. The billingSpec is configured within the callbacks.js script in the Formbuilder window.

The return value for the billingSpec should be the ShoppingCart. The billingSpec incrementally builds the ShoppingCart by pushing Product Id and Product Quantity to the ShoppingCart object. In this way, the app can be configured with a billingSpec that changes the Quantities of the Products based on the selection(s) the user makes in the input form.

For example, if the app is configured with three Non-Persistent Products with the following characteristics:

Product 1
    - Name: Product 1 Name
    - Id: 123
    - Rate: 1 iCredit(s)

Product 2
    - Name: Product 2 Name
    - Id: 456
    - Rate: 2 iCredit(s)

Product 3
    - Name: Compute Product Name
    - Id: 789
    - Rate: 1 iCredit(s)

The billingSpec would be the following:

function billingSpec(dataProvider)
{

    var Product1Quantity = 0;  
    var Product2Quantity = 0;
    var ComputeQuantity = 0;
    var Samples = dataProvider.GetProperty("Input.sample-id"); 

    for (var x = 0; x < Samples.length; ctr++)
    {
        // functions that calculate the Product1Quantity, Product2Quantity, and ComputeQuantity.  
    }

    ShoppingCart.push({ "Id": "123", "Quantity": Product1Quantity });  
    ShoppingCart.push({ "Id": "456", "Quantity": Product2Quantity });      
    ShoppingCart.push({"Id": "789", "Quantity": (Math.round(ComputeQuantity * 100) / 100)});

    return ShoppingCart;
}

Here the values Product1Quantity, Product2Quantity, and ComputeQuantity are first set to 0.

Next, the Samples variable is assigned to the values the user selected on the input form field with the Id sample-id which is a SampleChooser in this case. So, Samples will be an array of Samples selected in the input form. More information about using the GetProperty() function is available in the Formbuilder Documentation.

Then, as the user selects certain values on the input form, the billingSpec will simply increment the Quantity of the Products using any functions configured within the billingSpec.

Debugging your Billing Specification

There si a JavaScript debugger attached to the formbuilder tool which can help you to validate your BillingSpecs.

Refunds

BaseSpace users can contact BaseSpace Customer Support to request a refund.

Native App Billing Examples

function billingSpec(dataProvider)
{
    var TotalSizeInBytes = 0;
    var GbToBytes = 1073741824;
    var FusionOn = true;
    var HourPerGBFusionOff = 0.4;
    var HourPerGBFusionOn = 0.6;
    var TotalGB = 0;
    var ComputedQuantity = 0;
    var StrandedSamplesCount = 0;

    var Samples = dataProvider.GetProperty("Input.sample-id");       
    var SampleAttributes = dataProvider.GetProperty("Input.sample-id.attributes");  
    var ShoppingCart = [];   

    if (dataProvider.GetProperty("Input.CallFusions") === null)
        FusionOn = false;     

    for (var ctr = 0; ctr < Samples.length; ctr++)
    {
        TotalSizeInBytes += Samples[ctr].TotalSize;

        for (var ctr2 = 0; ctr2 < SampleAttributes[ctr].length; ctr2++ )
        {
            if (SampleAttributes[ctr][ctr2].Key === "Input.Stranded" && SampleAttributes[ctr][ctr2].Values[0] === "1")//SampleAttributes[ctr][ctr2].Values.length === 1)
                StrandedSamplesCount++;
        }
    }

    console.log('StrandedSamplesCount: ' + StrandedSamplesCount);
    console.log('TotalSizeInBytes: ' + TotalSizeInBytes);

    TotalGB = TotalSizeInBytes / GbToBytes;
    console.log('TotalGB: ' + TotalGB);

    ComputedQuantity = (TotalGB * (FusionOn ? HourPerGBFusionOn : HourPerGBFusionOff)) / .15;

    console.log('Quantity: ' + ComputedQuantity);
    console.log('FusionPrice: ' + (FusionOn ? HourPerGBFusionOn : HourPerGBFusionOff));

    //Add checking if total is less than 1 iCredit do not return anything?
    //if(StrandedSamplesCount > 0)
    ShoppingCart.push({ "Id": "2c92c0f844b4b1380144b80ac8bd0ff3", "Quantity": StrandedSamplesCount });       
    ShoppingCart.push({"Id": "2c92c0f84495ff3f0144b3640ba413c5", "Quantity": (Math.round(ComputedQuantity * 100) / 100)});

    return ShoppingCart;
}