TripleA Bitcoin Payments API (1.0.0)

Download OpenAPI specification:Download

Introduction

Welcome to TripleA! Our documentation provides everything you need to start accepting Bitcoin payments.

With Bitcoin payments, there’s no sensitive customer information to collect and store, and there are no cards to charge. Customers simply send funds (Bitcoin) from their computer or mobile device directly to a (unique one-time-use) payment address. TripleA monitors the blockchain and provides real-time payment updates. Updates can be shared by email, dashboard or API calls to your own backend.

You can accept bitcoin payments in a variety of ways.

  1. External URL payment form.
    Pay via URL redirection, which will lead to our hosted payment solution with our payment form.
  1. Embedded payment form.
    Pay within your site with the embedded payment form.
  1. Content Management System (CMS) plugins.
    Instant setup for your WooCommerce or OpenCart CMS.

  2. Custom Integration.

At TripleA we have tried our best to simplify the process of taking Bitcoin as a payment method.

Real Time Conversion

When a Bitcoin payment is initiated, we guarantee the exchange rate for 25 minutes. Once the funds arrive, the Bitcoin will be instantly converted to local currency at the guaranteed exchange rate.

TripleA takes the bitcoin exchange rates from several authoritative sources, such as Kraken
and Coinbase.

Funds that arrive after 25 minutes will be considered on a case by case basis.

Instant Confirmation

Once a Bitcoin payment is broadcasted to the Bitcoin network, TripleA will make a decision in a few seconds on whether the payment is good. If we determine a payment is good, the merchant will be guaranteed to receive the funds no matter what happens to the transaction thereafter.

Short Payment Topup

If buyers scan and pay using our QRCode, then we correct amount will be send everytime. However, sometimes buyers may be using other wallets or entering in amounts directly into their wallet. If they make a mistake and are short by a few cents, we will automatically top up to the requested amount and absorb that liability.

This is to enhance the merchant's and buyers' experience, as we know it is expensive for top up just a few cents in Bitcoin.

Account Types

Every merchant can have 1 or more wallets. Every api_id represents a different account that can receive cryptocurrency.

The basic account type is the TripleA Local Currency account. For this account type, the balances are stored as Local Currency. This means that when the account receives cryptocurrency, the account balance is credited in local currency at the guaranteed exchange rate.

When refunds or withdrawals are made in cryptocurrency from Local Currency accounts, the local currency is converted back into cryptocurrency at the prevailing exchange rate.

If your payment flow requires balances to be stored as cryptocurrency, then you can use a TripleA Custodial account. However, note that this account type does not support Real Time Conversion, Instant Confirmation or Short Payment Topup. Please reach out to support@triple-a.io if you require a custodial account.

Authentication and Credentials

Making a payment request is an authenticated API call. We use OAuth2 Client Credentials grant. OAuth2 is an open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.

payment_auth

TripleA uses the OAuth2 Client Credentials grant. To get a token, click here.

Security Scheme Type OAuth2
clientCredentials OAuth Flow
Token URL: https://api.triple-a.io/api/v1/oauth/token
Scopes:

    bearer_auth

    Merchants who make any request to the API need to insert the token in the Authorization header.

      Authorization : Bearer <access_token>
    
    Security Scheme Type HTTP
    HTTP Authorization Scheme bearer
    Bearer format "access_token"

    If you have not received your credentials, sign up on our website and you will receive an email with the credentials.

    You will receive Dashboard Login (a username and a password) and API credentials.

    The API credentials come in a form of :

      Client ID: oacid-*****************
      Client Secret: ********************************************
      Live API ID : HA**************************
      Sandbox API ID : HA**************************_t

    Client ID and Client Secret are used for the authorization in getting the access token, which is needed for API call.

    Live API ID is an identifier for a merchant to accept a single cryptocurrency.

    Sandbox API ID is an identifier for a merchant to accept a testnet cryptocurrency (eg. testnetBTC). These testnet BTC are worthless and are used only for testing if the payment system works.


    Reset Credentials

    For any reason, you can request to have your Client Secret reset. However, this will invalidate ALL outstanding access tokens. Please contact support@triple-a.io if you want to reset your Client Secret.

    Payments

    External URL Payment Form

    Overview

    One of the simplest ways to integrate with TripleA is using the External URL Payment Form, which basically is a URL redirection to Triple-A hosted payment page.

    Here is a flow diagram to illustrate the process :


    Payments Flow


    Before you get started

    • Get your TripleA credentials and merchant accounts .
    • Generate an oauth token.

    Integration Steps

    Based on the above diagram, below are the steps:

    1. Make a payment request

    You can start by making a payment request. For this method, please ensure you use 'type' : 'triplea' in the request body parameters. You may also supply your webhook url as notify_url and a notify_secret (for verification of the incoming webhook data) in the request body.

    A sucessful JSON response from the payment request would look like this :

      {
        "payment_reference": "AQH-100306-PMT",
        "crypto_currency": "testBTC",
        "crypto_address": "mhdJd37khi21VgeWcjMKM9BVxYj29tHvAt",
        "crypto_amount": 0.00080051,
        "order_currency": "USD",
        "order_amount": 5.29,
        "exchange_rate": 6608.33,
        "expiry_date": "2020-04-22T08:52:11.842Z",
        "access_token": "736511b84cdd67cfb0ecdf555828276aaddc26dc",
        "token_type": "Bearer",
        "expires_in": 3599,
        "hosted_url": "https://triple-a.io/app/v1/payment_form?payment_reference=AQH-100306-PMT&access_token=736511b84cdd67cfb0ecdf555828276aaddc26dd"
      }

    2. Redirect user to payment form

    You will need to redirect the user to our external URL payment form, by using the hosted_url received from the response.


    3. Wait for user payment

    Users will see the payment form with the necessary information of payment details.

    Normal Payment Form


    4. Payment notification

    When users have made a payment, you will receive the payment notification via email and/or webhook integration. This notification will be POSTed back to the notify_url that you have specified in the payment request.

    If there was no URL specified, it will default to the notification URL provided when the merchant was set up.

    In rare cases where a user overpaid by a considerable amount, refunds are possible.

    Embedded Payment Form

    Overview

    If you would like to have the payment form embedded in your site , without redirect to our external URL payment form, we provide the Embedded Payment Form method.

    Here is a flow diagram to illustrate the process :


    Payments Flow


    Before you get started

    • Get your TripleA credentials and merchant accounts .
    • Generate an oauth token.

    HTML Integration Steps

    Based on the above diagram, here are the steps:

    1. Request a payment form

    You can start by making a payment request. For this method, please ensure you use 'type' : 'widget' in the request body parameters. You may also supply your webhook url as notify_url and a notify_secret (for verification of the incoming webhook data) in the request body.

    A sucessful JSON response from the payment request would look like this :

      {
        "payment_reference": "AQH-100306-PMT",
        "crypto_currency": "testBTC",
        "crypto_address": "mhdJd37khi21VgeWcjMKM9BVxYj29tHvAt",
        "crypto_amount": 0.00080051,
        "order_currency": "USD",
        "order_amount": 5.29,
        "exchange_rate": 6608.33,
        "expiry_date": "2020-04-22T08:52:11.842Z",
        "access_token": "736511b84cdd67cfb0ecdf555828276aaddc26dd",
        "token_type": "Bearer",
        "expires_in": 3599,
        "hosted_url": "https://cdn.triple-a.io/widgets/triplea-ecommerce-payment-v1.1/?payment_reference=AQH-100306-PMT&access_token=736511b84cdd67cfb0ecdf555828276aaddc26dd"
      }

    2. Embed and update the payment form code

    Insert the below HTML code into your front-end template where you wish the payment form to appear. Use the payment_reference and access_token properties from the above JSON response to update the attribute values for the payment form.

      <triplea-ecommerce-payment-v1
        payment-reference=”<PAYMENT_REFERENCE_HERE>”
        access-token=”<ACCESS_TOKEN_HERE>”
      >
      </triplea-ecommerce-payment-v1>
      <script src="https://cdn.triple-a.io/widgets/triplea-ecommerce-payment-v1.1/js/app.js"></script>

    On page load, the payment form will be displayed. The user can proceed with payment.

    In the event you would like to hide the order details or the order currency (perhaps to adjust to the looks, styling or height of your application), you could insert these attributes inside the <triplea-ecommerce-payment-v1> tag :

    • order-details="hide" - To hide the order details.
    • order-currency="hide" - To hide the order currency.

    Example :

    <triplea-ecommerce-payment-v1
      payment-reference=”<PAYMENT_REFERENCE_HERE>”
      access-token=”<ACCESS_TOKEN_HERE>”
      order-details="hide"
      order-currency="hide"
    >
    </triplea-ecommerce-payment-v1>
    <script src="https://cdn.triple-a.io/widgets/triplea-ecommerce-payment-v1.1/js/app.js"></script>

    3. Payment notification

    When users have made a payment, you will receive the payment notification via email and/or webhook integration. This notification will be POSTed back to the notify_url that you have specified in the payment request.

    If you did not specify a notify_url, it will default to the notification URL provided when the merchant was set up. If this one is empty as well, an update notification will only be sent by email and not to your server.

    In the rare case where a user overpays by a considerable amount, a refund can be made.


    Iframe Integration Steps


    Configure the iframe

    This follows the same steps as for the above HTML Integration Steps.

    When using an iframe to display the payment form, use the below src URL in which you replace payment_reference and access_token values:

    <iframe
      id="triplea-payment-form"
      src="https://cdn.triple-a.io/widgets/triplea-ecommerce-payment-v1.1/?payment_reference=<VALUE>&access_token=<VALUE>"
      style="width:500px; height: 700px; border: 0;"
      scrolling="no"
    >
    </iframe>

    The payment form is responsive and adjusts to the width you assign it. Width and height in the above example are just suggestions to get you started.

    Similar to the HTML Integration Steps above, in the event you would like to hide the order details or the order currency (perhaps to adjust to the looks, styling or height of your application), you could insert these parameters on the iframe src URL :

    • order_details=hide - To hide the order details.
    • order_currency=hide - To hide the order currency.

    Example :

    <iframe
     id="triplea-payment-form"
     src="https://cdn.triple-a.io/widgets/triplea-ecommerce-payment-v1.1/?payment_reference=<VALUE>&access_token=<VALUE>&order_details=hide&order_currency=hide"
     style="width:500px; height: 700px; border: 0;"
     scrolling="no"
    >
    </iframe>

    Message Events

    The payment form uses the postMessage browserAPI to notify your parent window of relevant events happening to it. You can easily listen to and handle these events within your own site.

    Example code :

    (function(){
      window.addEventListener('message', e => {
        console.log('message received', e.data);
      }, false);
    })();

    These are events the payment form currently posts :

    • triplea.frameResized|<height> - When the payment form size changes. Example :
      • Payment form loads.
      • Payment form or user collection form is displayed.
      • Payment form is expired.
      • Cart details are open or closed.
    • triplea.formExpired - When the payment form timer is expired or payment reference & access token are invalid.
    • triplea.paymentTooLittle - When the payment is not made in full.
    • triplea.paymentSuccess - When the payment has been made.
    • triplea.bitcoinUrl|<bitcoinUrlValue> - When clicking upon the 'Open in Wallet' button, if decides to disable the navigation to a bitcoin wallet application.

    If you are using iframe, you can easily adjust the iframe's height when its contents change to avoid scrollbars (if desired) :

    (function(){
      window.addEventListener('message', e => {
        console.debug('message received:', e.data);
        let iframe = document.getElementById("triplea-payment-form");
        if(typeof e.data === 'string' && e.data.indexOf("|") > 0){
          const res = e.data.split("|");
          if(iframe && res[0] === 'triplea.frameResized'){
            iframe.style.height = res[1] + 'px';
          }
        }
      }, false);
    })();

    Some of the scenario examples where the messages are expected to fire :

    Scenario : User makes full payment.

    1. Payment form loads -> triplea.frameResized|<height> event occurs.
    2. If user opens cart details -> triplea.frameResized|<height> event occurs.
    3. User makes payment in full amount -> triplea.paymentSuccess and triplea.frameResized|<height> events occur.

    Scenario : User pays too little and then tops up for full amount

    1. Payment form loads -> triplea.frameResized|<height> event occurs.
    2. User makes mistake by paying too little.
    3. Payment form informs user the remaining amount due -> triplea.paymentTooLittle and triplea.frameResized|<height> events occur.
    4. User tops up before payment form timer expires -> triplea.paymentSuccess and triplea.frameResized|<height> events occur.

    Page Redirection

    By providing a success_url and cancel_url in the request body when making a payment request call, the embedded payment form will then redirect the whole (parent) page to either of those URLs depending on the payment outcome.

    If you prefer to avoid a full page redirect , don't provide the URLs and use the postMessage events above to customize the behaviour.

    For example:

    • You may use the triplea.paymentSuccess event to display a success message instead of staying on the payment form.

    Disable Navigation to A Bitcoin Wallet Application

    In the case where you do not want to redirect to a bitcoin wallet application, please insert a parameter disable_wallet_navigation=1 to the iframe src url.

    <iframe
      id="triplea-payment-form"
      src="https://cdn.triple-a.io/widgets/triplea-ecommerce-payment-v1.1/?payment_reference=<VALUE>&access_token=<VALUE>&disable_wallet_navigation=1"
      style="width:500px; height: 700px; border: 0;"
      scrolling="no"
    >
    </iframe>

    By inserting this parameter, clicking upon the 'Open in Wallet' button will not redirect to the wallet application.

    Instead, a postMessage event is triggered with message triplea.bitcoinUrl|<bitcoinUrlValue>. You may listen for this message and process the bitcoin url in anyway you see fit.


    Content Management System (CMS) Plugins

    Some of the features with this integration:

    • Create an account and activate instantly.
    • Setup the plugin within seconds.
    • Automatic Order Updates.

    Our TripleA's integration is available in :

    1. WooCommerce plugin.
    2. OpenCart plugin.

    Custom Integration

    If you want to integrate TripleA into a Point-Of-Sale system or you require more flexiblity to suit your particular needs, please contact us at support@triple-a.io and we will assist you with the integration.

    Refunds

    For refunds, only cryptocurrency will be returned to the customer.

    When refunding, the merchant must refund from a particular payment, and must also have have sufficient available local currency balances to refund from a local currency account or sufficient cryptocurrency balances to refund from a custodial account.

    Please note that real available balances can be used to refund
    cryptocurrency, while test available balances can only be used to refund testnet cryptocurrency.

    For local currency accounts, the amount of cryptocurrency returned does not depend on the amount of cryptocurrency sent, but the amount of local currency that is received as payment. The maximum amount that can be refunded cannot exceed the local currency amount received.

    In the case of custodial accounts, the maximum of amount cryptocurrency that can be refunded cannot exceed the cryptocurrency amount received.

    This is the refund flow:

    1. A refund is initiated against a payment. The email address of the refund recipient must be provided.

    2. The refund recipient gets an email informing them of their refund. There is a link in the email that they can click.

    3. By clicking on this link, the refund recipient is brought to a form where they can see how much cryptocurrency they will receive. For refunds from a local currency account, the exchange rate will be set once the recipient enters their receiving crypto address. Refunds from a custodial account do not have a meaningful exchange rate, so the exchange rate can be ignored.

    4. The merchant should receive a notification email once the refund recipient has confirmed their crypto address.

    5. Once the transfer of cryptocurrency has been made, another notification email will be sent to the merchant. There will also be a corresponding payout webhook notification.

    Withdrawals

    For withdrawals, either local currency or cryptocurrency can be sent to a customer.

    When initiating a local currency withdrawal, we will use the provided email address to unqiuely identify the customer who will receive the funds. Every customer who receives local currency will need to undergo our KYC process before they can receive funds into their bank account.

    Cryptocurrency Withdrawals

    The total amount of cryptocurrency that can be withdrawn from a merchant depends on the amount of local currency or cryptocurrency (custodial) available balances the merchant has.

    When withdrawing cryptocurrency from a local currency account, the amount of cryptocurrency received will depend on the prevailing exchange rates.

    This is the cryptocurrency withdrawal flow:

    1. A withdrawal is initiated against a merchant's available balance. The email address of the withdrawal recipient must be provided.

    2. The withdrawal recipient gets an email informing them of their withdrawal. There is a link in the email that they can click.

    3. By clicking on this link, the withdrawal recipient is brought to a form where they can see how much cryptocurrency they will receive. For withdrawals from a local currency account, the exchange rate will be set once the recipient enters their receiving crypto address. Withdrawals from a custodial account do not have a meaningful exchange rate, so the exchange rate can be ignored.

    4. The merchant should receive a notification email once the withdrawal recipient has confirmed their crypto address.

    5. Once the transfer of cryptocurrency has been made, another notification email will be sent to the merchant. There will also be a corresponding payout webhook notification.

    Local Currency Withdrawals

    The total amount of local currency that can be withdrawn from a merchant depends on the amount of local currency or cryptocurrency (custodial) available balances the merchant has.

    When withdrawing local currency from a custodial account, the amount of local currency received will depend on the prevailing exchange rates.

    The local currency withdrawal flow is much simpler. Just provide the email address of the recipient and specify the amount to be withdrawn. if the recipient has already completed KYC, the funds will be transferred to their bank account. If they have not undergone KYC, we will reach out to them to complete KYC. Upon completion of KYC, then we will transfer the funds to their bank account.

    Webhook Notifications

    We use webhook notifications to let you know when a payment is successful or a payout has been executed.

    The receiving webhook can be specified in payment requests, refund requests and withdrawal requests as the notify_url. If you would like to verify the authenticity of notification to your webhook, you can also specify the notify_secret that will be used to sign the notification.

    Each notification is in the form of an HTTP POST to the webhook URL. If the webhook reponds with a HTTP Status code of 2XX, then we consider the notification to be successful. For any other HTTP status code, or if the URL is unreachable, we will retry up to five times in the following intervals (after the initial webhook notification): 30 seconds, 60 seconds, 300 seconds, 600 seconds, 600 seconds.

    Webhook Notification Security

    If you would like to verify the authenticity of a webhook notification, we provide a signature in the Triplea-Signature HTTP header.

    The header has the format t=<unix-timestamp>,v1=<hex-encoded-signature> where t is the unix timestamp and v1 is the hex-encoded signature.

    A shared secret (notify_secret) is used to verify this signature and can either be:

    1. Provided by you during the payment request, refund request or withdrawal request. You may reuse the same secret.

    2. Generated by the system, if no secret is provided during the payment request, refund or withdrawal. This will be a random secret that only applies for that particular payment request, refund request or withdrawal request.

    To verify the header signature, the developer will take the timestamp and concatenate it with the raw request body, using a period . as a separator <unix-timestamp>.<raw-request-body> and apply the hmac-sha256 algorithm with notify_secret. This gives a signature which can be compared to the v1 from the HTTP header.

    If the signatures match, compare the t against the current timestamp. If they are within tolerance then the webhook is authenticated. The recommended tolerance is 300 seconds.

    Here is some sample Node.js code for signature verification using express:

    'use strict';
    
    // crypto module
    const crypto = require('crypto');
    
    // This example uses Express to receive webhooks
    const app = require('express')();
    
    // Use body-parser to retrieve the raw body as a buffer
    const bodyParser = require('body-parser');
    
    const secret = 'Cf9mx4nAvRuy5vwBY2FCtaKr!@#';
    
    // Match the raw body to content type application/json
    app.post(
      '/webhook', 
      bodyParser.raw({type: 'application/json'}), 
      (req, res) => {
        const sig = req.headers['triplea-signature'];
    
        let timestamp, signature;
        for (let sig_part of sig.split(',')) {
          let [key, value] = sig_part.split('=');
    
          switch (key) {
            case 't':
              timestamp = value;
              break;
            case 'v1':
              signature = value;
              break;
          }
        }
    
        // calculate signature
        let check_signature = crypto.createHmac('sha256', secret)
          .update(`${timestamp}.${req.body}`)
          .digest('hex');
    
        // current timestamp
        let curr_timestamp = Math.round((new Date()).getTime() / 1000);
    
        if (
          signature === check_signature && // verify signature
          Math.abs(curr_timestamp - timestamp) <= 300 // timestamp within tolerance
        ) {
          // signature validates ... do stuff
          return res.status(200).end();
        } else {
          return res.status(400).end();
        }
      }
    );
    
    app.listen(10003, () => console.log('Listen to 10003'));
    

    And here is some sample webhook data you can validate your signature verification code against:

    1. Raw request body: - {"event":"payment","api_id":"HA1587722191gQKF_t","payment_reference":"BQB-473822-PMT","crypto_address":"mjBjfSDbEHjLq6Gxko6kv9xgU29tA8s5D1","crypto_currency":"testBTC","crypto_amount":0.00021292,"order_currency":"USD","order_amount":2.17,"exchange_rate":10191.9,"expiry_date":"2020-09-29T01:24:11.026Z","unconfirmed_crypto_amt":0,"confirmed_crypto_amt":0.00021292,"unconfirmed_order_amt":0,"confirmed_order_amt":2.17,"status":"confirmed","status_date":"2020-09-29T01:12:02.431Z","webhook_data":{"order_id":"ABC12345-2"},"payment_tier":"good","payment_tier_date":"2020-09-29T01:09:51.272Z","payment_amount":2.17,"payment_crypto_amount":0.00021292,"cart":{"items":[{"amount":10.99,"quantity":1,"label":"A tale of 2 cities","sku":"2736829"}],"shipping_cost":2.57,"shipping_discount":0,"tax_cost":0.73}}

    2. Notification secret - Cf9mx4nAvRuy5vwBY2FCtaKr!@#

    3. Signature header - t=1601341922,v1=180c9e8f4b9a49fde518e873e886d3a35e41f0504d1e86c5658a8fe42daef27d

    Payment Notification And Instant Confirmation

    TripleA sends payment notifications to your payment notification webhook via an HTTP POST. Every time a buyer sends a Bitcoin transaction to a payment address, it generates 2 payment notifications. One when the transaction is broadcast and the other when the transaction is added to the blockchain.

    For a local currency account, payment_tier and payment_amount in the payment notification are the most important things to consider, to determine how much money you will receive and whether to deliver the goods and services. Instant Confirmation is available on all our local currency accounts by default.

    In the custodial account payment notification, consider payment_tier and payment_crypto_amount. Please note that there is no Instant Confirmation for custodial accounts.

    The payment_tier is the overall state of the payment and it can be in 1 of 5 states: none, short, hold, good and invalid

    1. none - no payment has been detected (yet). The merchant should not deliver the goods and services.

    2. short - the payment is short of the requested amount. The merchant should not deliver the goods and services.

    3. hold - the payment is equal to or greater then the requested amount, but the payment cannot be instantly confirmed. The merchant should not deliver the goods and services.

    4. good - the payment is equal to or greater then the requested amount and TripleA has determined that you can now deliver the goods and services to the buyer. 97% of transactions that we process have instant confirmation and are determined good within a few seconds of being broadcasted to the Bitcoin network. Your funds are now guaranteed.

    5. invalid - the payment was rejected by the Bitcoin network. This is a very rare occurence.

    The payment_amount is the guaranteed amount of local currency that you will receive into your local currency account. Even if the payment_tier remains as short or hold or later becomes invalid.

    The payment_crypto_amount is the amount of cryptocurrency that you will receive into your custodial account.

    Payment Tier Progression

    1. A none payment can go to : short, hold, good or invalid.

    2. A short payment can go to: hold, good or invalid.

    3. A hold payment can go to: good or invalid.

    4. A good payment is always good, no matter what actually happens on the blockchain.

    5. A invalid payment is always invalid as it has been rejected by the blockchain.

    Payment Stages

    Payment Notification Schema