NAV undefined
undefined
javascript

Introduction

Welcome to the BitTube TubePay API.

You can use our API to set up products for sale via the AirTime Module, as an additional way to generate revenue from your users. With the module you can also easily place donate buttons on your page that allow the user to donate whatever amount they want.

This documentation covers:

How TubePay Works

The following diagram shows an high level overview of how your website and TubePay interact with each other:

Purchase flow

The TubePay backend manages a database of your products. This database contains pricing and some meta information, but not the content itself. You can register and manage these goods using the TubePay Products API.

The products can be embedded on your web page using HTML Tags with special data attributes (see Placing Products). The location of the HTML tag determines the position of the product on the page, or if the product hasn't been paid yet, the position of its placeholder. The special HTML tags are recognised by the AirTime Module, which needs to be included on every page that contains products for sale.

When a user buys a product, the module handles the payment process by creating a transaction on the client and sending it to TubePay servers for relaying and verification. After successful payment the module receives a payment certificate, which in turn is used to fetch the content of the product from a special HTTP Endpoint provided by you (see Serving Products).

AirTime Module

An example of HTML tags to install BitTube AirTime Module in meta tag verification mode.

<meta name="airtime-platform-id" content="[Platform ID]">
<meta name="airtime-platform-display" content="[Platform Name]">
<script
  src="https://bittubeapp.com/tubepay/airtime.loader.js"
  data-verify="meta"
  data-autostart="true">
</script>

To use data-verify="file" you'll need to add airtime-platform.json to the root of your server (must be accesible at /airtime-platform.json), the file must contain at least the following information.

{
  "platformUUID": "[Platform ID]",
  "platformDisplayName": "[Platform Name]"
}

Make sure that [Platform ID] and [Platform Name] have your information.

To be able to use the TubePay functionality you'll need to have the BitTube AirTime Module installed on your site. Installing the module enables you to receive income from AirTime generated by your users as well as sell products and receive donations through the TubePay system.

The installation is very simple, you just need to register a new platform from the extension and insert the provided HTML into your site.

After installation the module adds a small banner that floats by default at the bottom right of the page, the banner will appear as just the BitTube logo until the user hovers over it.

Banner Collapsed

Banner Expanded

The initial corner of the banner can be specified with data-banner-position, users can move the banner anywhere on the screen they want and it'll remember the user set position for next visit.

On load the module will verify the platform information, how this is done can be controlled with the data-verify attribute.

Parameter Required Description
data-verify Yes Type of platform verification check, (valid values are meta and file)
data-autostart No Start AirTime capture automatically after load (defaults to false)
data-ensure-logs-sent No Add a blocking handler to page close to send incomplete logs (defaults to false)
data-banner-position No The initial position for the banner
(valid values are top-left, top-right, bottom-left, bottom-right)

TubePay Products API

Authentication

To authorize a request, use the following code:

const ENDPOINT = '[API Endpoint]';
const apiKey = '[apiKey]';
const apiSecret = '[apiSecret]';

// Basic Auth, Authorization Header
fetch(ENDPOINT, { 
  headers: new Headers({
    'Authorization': 'Basic '+btoa(apiKey + ':' + apiSecret), 
  }), 
});

// Query Parameters
fetch(ENDPOINT + '?apiKey=' + apiKey + '&apiSecret=' + apiSecret);

Make sure to replace [apiKey] and [apiSecret] with your information.

All requests to the TubePay Products API must be authenticated with your apiKey and apiSecret.

To use the TubePay API you'll currently need to have registered for an AirTime Module Platform.

To authenticate your requests, either use the Basic HTTP Authorization header (user and password) as in the examples, or if more convinient for you, you can pass the apiKey and apiSecret as query parameters by the same name.

Product Information Structure

{
  "active": true,
  "id": "2jvt0grvv",
  "price": 1000000,
  "secret": "[Secret]",
  "title": "Example Product",
  "validFor": 0,
  "created": 1559562250035,
  "updated": 1559562250035,
}
Parameter Description
id Product ID. Assigned by API on creation, only enforced to be unique to your apiKey.
active Whether the product is active, or not. Inactive products cannot be purchased or viewed, and will be labeled as such if used on your website.
price Price of the product in TUBE Atomic Units. Must be at least 0.01 TUBE. (100000000 Atomic Units == 1 TUBE)
secret The product specific purchase certificate secret. Use this to authenticate purchase certificates upon content delivery.
title Displayed name of the product, shown to the user in the product information, purchase history and confirmation screen. Must be between 5 and 300 characters.
validFor The amount of time, in milliseconds, that a purchase will be valid for after purchase confirmation. Must be at least 10 minutes, or can be set to 0 for indefinite.
created The timestamp of when the product was created via the API.
updated The timestamp of when the product information was last updated via the API.
ownerContentName Optionally, the unique User ID of who the product belongs to on your platform, as specified on creation. If specified the AirTime User who this name is linked to is the one who gets paid.

Get All Products

const ENDPOINT = 'https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products';
const apiKey = '[apiKey]';
const apiSecret = '[apiSecret]';

fetch(ENDPOINT, { 
  headers: new Headers({
    'Authorization': 'Basic '+btoa(apiKey + ':' + apiSecret), 
  }), 
});

The above command returns JSON structured like this:

{
  "success": true,      // Whether the call itself was successful.
  "message": "Success", // If an error occurred, it would be stated here.
  "products": [
    {...},              // List of products. See "Product Information" above for structure.
    {...}
  ]
}

This endpoint retrieves all products and their information, as described above.

HTTP Request

GET https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products

Get a Specific Product

const ENDPOINT = 'https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products/<ID>';
const apiKey = '[apiKey]';
const apiSecret = '[apiSecret]';

fetch(ENDPOINT, { 
  headers: new Headers({
    'Authorization': 'Basic '+btoa(apiKey + ':' + apiSecret), 
  }), 
});

The above command returns JSON structured like this:

{
  "success": true,      // Whether the call itself was successful.
  "message": "Success", // If an error occurred, it would be stated here.
  "product": {...}      // Product Information Object. See "Product Information" above for structure.
}

This endpoint retrieves a specific product.

HTTP Request

GET https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products/<ID>

URL Parameters

Parameter Description
ID The ID of the product to retrieve

Create a new Product

const ENDPOINT = 'https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products';
const apiKey = '[apiKey]';
const apiSecret = '[apiSecret]';

const body = {
  title: 'New Product',
  price: 1000000            // 0.01 TUBE
  validFor: 1000 * 60 * 10, // 10 minutes
};

fetch(ENDPOINT, { 
    method: 'post', 
    headers: new Headers({
      'Authorization': 'Basic '+btoa(key + ':' + secret), 
      'Content-Type': 'application/json'
    }), 
    body: JSON.stringify(body)
  });

The above command returns JSON structured like this:

{
  "success": true,      // Whether the call itself was successful.
  "message": "Success", // If an error occurred, it would be stated here.
  "product": {...}      // Product Information Object. See "Product Information" above for structure.
}

This endpoint creates a new product with the given information.

HTTP Request

POST https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products

JSON Parameters

Parameter Required Description
title Yes Title of the product
price Yes Price of the product, in atomic units
validFor Yes How long purchase of the product is valid for, set to zero for no limit
ownerContentName No Owner of this product. If specified the AirTime User who this name is linked to is the one who gets paid.

Update a product information

const ENDPOINT = 'https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products/<ID>';
const apiKey = '[apiKey]';
const apiSecret = '[apiSecret]';

const body = {
  title: 'Updated Product',
  price: 1000000            // 0.01 TUBE
  validFor: 1000 * 60 * 10, // 10 minutes
};

fetch(ENDPOINT, { 
    method: 'post', 
    headers: new Headers({
      'Authorization': 'Basic '+btoa(key + ':' + secret), 
      'Content-Type': 'application/json'
    }), 
    body: JSON.stringify(body)
  });

The above command returns JSON structured like this:

{
  "success": true,      // Whether the call itself was successful.
  "message": "Success", // If an error occurred, it would be stated here.
  "product": {...}      // Product Information Object. See "Product Information" above for structure.
}

This endpoint updates a product with the given information. All JSON parameters are optional.

HTTP Request

POST https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products/<ID>;

URL Parameters

Parameter Description
ID The ID of the product to update

JSON Parameters

Parameter Description
title Title of the product
price Price of the product, in atomic units
validFor How long purchase of the product is valid for, set to zero for no limit

Deactivate a product

const ENDPOINT = 'https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products/<ID>';
const apiKey = '[apiKey]';
const apiSecret = '[apiSecret]';

fetch(ENDPOINT, { 
    method: 'delete', 
    headers: new Headers({
      'Authorization': 'Basic '+btoa(key + ':' + secret), 
    }), 
  });

The above command returns JSON structured like this:

{
  "success": true,      // Whether the call itself was successful.
  "message": "Success", // If an error occurred, it would be stated here.
}

This endpoint deactivates a product.

HTTP Request

DELETE https://us-central1-bittube-airtime-extension.cloudfunctions.net/tubepay/seller/products/<ID>;

URL Parameters

Parameter Description
ID The ID of the product to update

Placing Products

Products

<div
  data-tubepay-product="[Product ID]"
  data-tubepay-type="[Type]"
  data-tubepay-source="[Product Source]"
  data-tubepay-placeholder="[Placeholder Image Source]"
  data-tubepay-fiat-currency="[Currency]">
</div>

<span
  data-tubepay-product="[Product ID]"
  data-tubepay-type="[Type]"
  data-tubepay-source="[Product Source]"
  data-tubepay-placeholder="[Placeholder Image Source]"
  data-tubepay-fiat-currency="[Currency]">
</span>

To include a product on your website for purchase, place a div or span element with these attributes. The AirTime Module will find them (even if added dynamically) and properly display and manage the product.

Data Attributes

Parameter Required Description
data-tubepay-product Yes The ID of the product
data-tubepay-type Yes The product type, I.E. how the product should be displayed
(valid values are video audio image iframe html link)
data-tubepay-source Yes Source of the product to be fetched upon purchase
data-tubepay-placeholder No Source of placeholder image to display before purchase
data-tubepay-fiat-currency No Currency to translate the amount of TUBE to

Donations

<div
  data-tubepay-donate="[Amount]"
  data-tubepay-creator-name="[Creator ID]"
  data-tubepay-creator-display="[Creator Name]"
  data-tubepay-fiat-currency="[Currency]">
</div>

<span
  data-tubepay-donate="[Amount]"
  data-tubepay-creator-name="[Creator ID]"
  data-tubepay-creator-display="[Creator Name]"
  data-tubepay-fiat-currency="[Currency]">
</span>

To include a button on your website for donations, place a div or span element with these attributes. The AirTime Module will find them (even if added dynamically) and properly display and manage the donation button.

Data Attributes

Parameter Required Description
data-tubepay-donate Yes Amount to donate. Can be left empty, but must exist. Defaults to 1 TUBE
data-tubepay-creator-name No Creator platform unique ID to donate to
data-tubepay-creator-display No Display name for the recipient to be shown upon donation
data-tubepay-fiat-currency No Currency to translate the amount of TUBE to

Serving Products

Purchase Certificates

Upon purchase, the module will request the product source with URL parameter tubePayCert, which you will have to check the validity of before you serve the content.

It is your responsibility to properly protect your content with the proper certificate checks.

How to verify purchase certificate

const productSecret = '[SECRET FOR PRODUCT]';
const certificate = '[CERTIFICATE FROM REQUEST]';

const s = certificate.split('.');
const payload = s[0];
const given_signature = s[1];

const payloadAndSecret = payload + productSecret;
const signature = crypto.createHash('sha512').update(payloadAndSecret).digest('hex');
const isValid = given_signature === signature;

if (!isValid) {
  // Fail the request, this certificate has an invalid signature.
} else {
  const info = JSON.parse((Buffer.from(payload, 'base64')).toString('ascii'));
  const epochNow = Date.now() / 1000;
  if (info.exp < epochNow) {
    // Fail the request, this certificate is expired.
  } else {
    // Success.
    // Certificate is valid and still in date.
  }
}

The payment certificate is composed by 2 parts separated by a dot. The first is the payload, consisting of base64 encoded JSON. The second is the signature, which is the sha512 of the concatenation of the payload and the products specific secret. To check validity, generate the sha512 as described and compare it to the signature. If the certificate is invalid, or has expired, the requested content should not be served.

How the certificate is generated

const productSecret = '[SECRET FOR PRODUCT]';
const certPayload = {
  exp: number  // UNIX Epoch after which this certificate should no longer be accepted
  ito: string  // Who this certificate was issued to (firebase user id)
  jti: string  // Unique ID for certificate
};

const certPayloadB64 = Buffer.from(JSON.stringify(certPayload)).toString('base64');
const payloadAndSecret = certPayloadB64 + productSecret;
const signature = crypto.createHash('sha512').update(payloadAndSecret).digest('hex');

const issuedCertificate = certPayloadB64 + '.' + signature;

Shown to the right is the manner in which the certificates are generated on our end, and what additional information they contain.