NAV Navbar
shell javascript

Overview

Welcome to GBL's API! You can use this API to integrate cryptocurrencies into your application.

API Endpoint

http://127.0.0.1/

This API provides the ability to perform the following merchant activities:

To get the best experience out of the examples provided, we strongly recommend filling out your credentials in the provided fields at the top of the navigation bar.

Conventions

Dates and Times

All timestamps will include a date and time in UTC expressed according to the simplified extended ISO 8601.

Unique Identifiers

Throughout this documentation we will be using universally unique identifiers (UUIDs). All entities (e.g. User, Address) can be identified by a Version 4 (random) UUID.

Errors

All failed requests will include a response body indicating that the request was unsuccessful and a brief description of the error.

{
  "success": false,
  "error": "<error text>"
}

The API uses the following HTTP status codes:

Error Code Meaning
400 Bad Request The server could not understand the request due to invalid syntax.
403 Forbidden The request was valid, but the server is refusing action.
404 Not Found The specified resource could not be found.
409 Conflict The request conflicts with the current state of the server.
422 Unprocessable Entity The request was well-formed but was unable to be followed due to semantic errors.
500 Internal Server Error A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.

It is worth noting that GBL employs IP restrictions on requests made to our API. If you are encountering consistent errors, consider reaching out to a support specialist to confirm your IP has been allowed.

Changelog

[1.3.0] - 2021-01-26

[1.2.0] - 2020-05-31

[1.1.0] - 2020-03-25

[1.0.0] - 2020-03-12

Changed

Integration

Before integrating with the API, you must make the decision regarding how users in your system will be identified in GBLPay Crypto.

You have two options:

  1. Rely solely on the User identifiers GBLPay Crypto generates (managed internally and referred to as User IDs) ; or
  2. Provide your own User identifiers (referred to as User References) which link back to your own system's User records.

Many APIs which handle user-based activity (deposits, withdrawals and refunds) offer two modes of invocation; it is up to you to choose one mode or the other, and use this mode for the lifetime of your application.

Purpose "User ID" mode1 "User Reference" mode1
Create a user POST /wallet/user, yields a User ID for future API calls (done internally by you; yields a User Reference for future API calls)
Obtain a deposit address POST /wallet/deposit { userId: '???' } POST /wallet/deposit { userReference: '???' }
Process a withdrawal POST /wallet/withdrawal { userId: '???' } POST /wallet/withdrawal { userReference: '???' }
Process a refund POST /wallet/refund { userId: '???' } POST /wallet/refund { userReference: '???' }
Query risk for a user PUT /wallet/risk { userId: '???' } PUT /wallet/risk { userReference: '???' }

1parameters listed here are a subset of those required by the API, and are simplified for brevity; refer to their individual documentation sections for a full explanation.

In GBLPay Crypto, a User ID will always be a UUID v4.

With your own system, whatever you provide as a User Reference must simply represent "user uniqueness" in your own system; it could be a UUID, or a username, or an email address as long as it is consistent, and used consistently as a User Reference with every GBLPay Crypto API invocation.

In all situations where either a User ID (internally-generated by GBLPay Crypto) or a User Reference (created and managed by you) must be provided, you must provide one or the other (based on your initial integration decision), but not both.

Currencies

In the context of these APIs a currency refers to a supported cryptocurrency, like Bitcoin. The 3-4 character currency code is often used in place of the full name of the currency.

Retrieve Available Currencies

curl -u username:password -X GET \
  http://127.0.0.1/wallet/currencies
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'GET',
  url: 'http://127.0.0.1/wallet/currencies'
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "currencies": [
      {
        "name": "Bitcoin",
        "code": "BTC"
      }
    ]
  }
}

Retrieves all available currencies.

HTTP Request

GET
/wallet/currencies

Parameters

n/a

Responses

Code Reason
200 Retrieving the currencies was successful.
400 Invalid request due to missing or incorrect parameters.
500 An unexpected error occurred and the request was unsuccessful.

User

A user is a unique entity belonging to a tenant, and a user can have a set of deposit addresses for each available currency. Deposits and withdrawals will be linked back to a user and currency.

When integrating GBLPay Crypto for the first time, you must choose either to work with GBLPay Crypto's internally-generated User IDs, or your own User References; see Integration for details.

Create a User

curl -u username:password -X POST \
  http://127.0.0.1/wallet/user \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/x-www-form-urlencoded'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'POST',
  url: 'http://127.0.0.1/wallet/user',
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd',
    'Content-Type': 'application/x-www-form-urlencoded'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "user": {
      "id": "1234abcd-123a-4abc-8123-123456789abc",
      "tenantId": "01234567-890a-4cde-8012-34567890abcd",
      "createdAt": "2019-01-01T12:00:00.000Z",
      "updatedAt": "2019-01-01T12:00:00.000Z"
    }
  }
}

Creates a single User.

HTTP Request

POST
/wallet/user

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
userReference body string No n/a A user external reference (case-sensitive string).

Responses

Code Reason
200 User creation was successful.
400 Invalid request due to missing or incorrect parameters.
500 An unexpected error occurred and the request was unsuccessful.

Retrieve a User

curl -u username:password -X GET \
  http://127.0.0.1/wallet/user?userId=fedcba98-7654-3210-8012-34567890abcd \
  -H 'X-Tenant-Key:01234567-890a-4cde-8012-34567890abcd'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'GET',
  url: 'http://127.0.0.1/wallet/user',
  qs: {
    userId: 'fedcba98-7654-3210-8012-34567890abcd'
  },
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "user": {
      "id": "1234abcd-123a-4abc-8123-123456789abc",
      "tenantId": "01234567-890a-4cde-8012-34567890abcd",
      "createdAt": "2019-01-01T12:00:00.000Z",
      "updatedAt": "2019-01-01T12:00:00.000Z"
    }
  }
}

Retrieves information about a single user.

HTTP Request

GET
/wallet/user

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
userId query string Yes* n/a A user identifier (uuid).
userReference query string Yes* n/a A user external reference (case-sensitive string).

* Either parameter is required (but not both)

Responses

Code Reason
200 Retrieving user details was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find the specified user.
500 An unexpected error occurred and the request was unsuccessful.

Deposit

A deposit address is owned by a user and associated to a single currency. A user's address specifies the destination to send funds to from an external wallet.

Addresses are automatically generated for users as needed. These addresses may rotate after usage depending upon the configured rotation strategy. This means that a user may have multiple addresses associated with their account at any given time.

Retrieve a deposit address

curl -u username:password -X POST \
  'http://127.0.0.1/wallet/deposit' \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'userReference=PLR-7654-3210-8012-34567890abcd&currency=BTC'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'POST',
  url: 'http://127.0.0.1/wallet/deposit',
  form: {
    userReference: 'PLR-7654-3210-8012-34567890abcd',
    currency: 'BTC'
  },
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "address": "1abcdefghijklmnopqrstuvwzyzABCDEFG"
  }
}

Retrieves the current deposit address for a single user and currency. A new user will be created if the provided userReference does not exist.

HTTP Request

POST
/wallet/deposit

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
userId body string Yes* n/a A user identifier (uuid).
userReference body string Yes* n/a A user external reference (case-sensitive string).
currency body string Yes n/a Currency code (3 or 4 characters).

* Either parameter is required (but not both)

Responses

Code Reason
200 Retrieving an address was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find the specified user/currency.
500 An unexpected error occurred and the request was unsuccessful.

Transactions

Uniqueness

Uniqueness of records retrieved from the API may be observed either by a record's own "id" field, or by the union of its representation of data on the Blockchain, i.e. txid, toAddress and vout.

Retrieve Blockchain Transactions

curl -u username:password -X GET \
  http://127.0.0.1/wallet/transactions?currency=BTC&transactionType=send&limit=25&offset=0&userId=fedcba98-7654-3210-8012-34567890abcd \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'GET',
  url: 'http://127.0.0.1/wallet/transactions',
  qs: {
    currency: 'BTC',
    transactionType: 'send',
    limit: 25,
    offset: 0,
    userId: 'fedcba98-7654-3210-8012-34567890abcd'
  },
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "transactions": [
      {
        "id": "4321abcd-123a-4abc-8123-123456789abc",
        "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
        "amount": 1.0,
        "currency": "BTC",
        "confirmations": 6,
        "fromAddress": "1abcdefghijklmnopqrstuvwzyzGFEDCBA",
        "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
        "vout": 0,
        "transactionType": "Send",
        "processState": "Succeeded",
        "userId": "1234abcd-123a-4abc-8123-123456789abc",
        "userReference": "PLR-7654-3210-8012-34567890abcd",
        "createdAt": "2019-01-01T12:00:00.000Z",
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "trusted": true,
        "risk": "unknown"
      }
    ],
    "pageInfo": {
      "limit": 25,
      "offset": 0,
      "totalEntries": 100,
      "totalPages": 4
    }
  }
}

Retrieves a list of blockchain transactions. These results represent the current state of the transactions and may be subject to change.

We only track confirmations for deposits up to a maximum of 10 confirmations. Once a transaction has reached or exceeded 10 confirmations we no longer update the record.

Transactions can be uniquely identified by a combination of the toAddress and txid. It is necessary to look at both fields to determine uniqueness since multiple deposits/withdrawals can be a part of the same blockchain transaction and thus share the same txid.

Third-party guarantee of the transaction is indicated by the trusted field; a value of "true" indicates trust, and a value of "false" indicates the third-party provider has insufficient information on the transaction to be able to guarantee risk of double-spend or other fraudulent activity.

HTTP Request

GET
/wallet/transactions

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
currency query string Yes n/a Currency code (3 or 4 characters).
transactionType query string no all Transaction type from send, receive, generate, immature, orphan, overflow, refund (must be in lowercase).
limit query number no 25 The maximum number of records to return (default 25).
offset query number no 0 The starting index for the records (default 0).
userId query string no n/a A user identifier (uuid).
userReference query string no n/a A user external reference (case-sensitive string).

Responses

Code Reason
200 Retrieving the transactions was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find transactions for the specified filter.
500 An unexpected error occurred and the request was unsuccessful.

Withdrawals

Withdrawals allow a user to move funds to an external wallet address. These transactions will be prioritized by miners on the network according to the fees set and will take some amount of time to process.

Fees

Fees are generally used to influence the likelihood that block-miners on the blockchain will pick up a transaction in a desired amount of time. Fees for withdrawals, by default, are paid by the wallet-owner. For alternate fee structures, contact the administrator for your installation.

Create a Withdrawal

curl -u username:password -X POST \
  http://127.0.0.1/wallet/withdraw \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'userId=fedcba98-7654-3210-8012-34567890abcd&currency=BTC&amount=0.1&fee=0.01&toAddress=1abcdefghijklmnopqrstuvwzyzABCDEFG'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'POST',
  url: 'http://127.0.0.1/wallet/withdraw',
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    userId: 'fedcba98-7654-3210-8012-34567890abcd',
    currency: 'BTC',
    amount: '0.1',
    toAddress: '1abcdefghijklmnopqrstuvwzyzABCDEFG'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "withdraw": {
      "id": "12345678-abcd-4321-8765-abcdef123456",
      "toAccountId": "fedcba98-7654-3210-8012-34567890abcd",
      "currency": "BTC",
      "amount": 0.1,
      "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
      "createdAt": "2019-01-01T12:00:00.000Z",
      "updatedAt": "2019-01-01T12:00:00.000Z"
    }
  }
}

HTTP Request

POST
/wallet/withdraw

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
userId body string Yes* n/a A user identifier (uuid).
userReference body string Yes* n/a A user external reference (case-sensitive string).
currency body string Yes n/a Currency code (3 or 4 characters).
amount body number Yes n/a Withdrawal (floating point value).
toAddress body string Yes n/a External wallet address to withdraw to.

* Either parameter is required (but not both)

Responses

Code Reason
200 Creating the withdrawal was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find the specified user/currency.
500 An unexpected error occurred and the request was unsuccessful.

Refunds

Refunds allow a user to return funds to an external wallet address. These transactions will be prioritized by miners on the network according to the default fees set and will take some amount of time to process. It is assumed that the tenant will pay the transaction fee to process the refund.

Create a Refund request

curl -u username:password -X POST \
  http://127.0.0.1/wallet/refund \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'userId=fedcba98-7654-3210-8012-34567890abcd&currency=BTC&amount=0.1&toAddress=1abcdefghijklmnopqrstuvwzyzABCDEFG'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'POST',
  url: 'http://127.0.0.1/wallet/refund',
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    userId: 'fedcba98-7654-3210-8012-34567890abcd',
    currency: 'BTC',
    amount: '0.1',
    toAddress: '1abcdefghijklmnopqrstuvwzyzABCDEFG'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "refund": {
      "id": "12345678-abcd-4321-8765-abcdef123456",
      "toAccountId": "fedcba98-7654-3210-8012-34567890abcd",
      "currency": "BTC",
      "amount": 0.1,
      "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
      "createdAt": "2019-01-01T12:00:00.000Z",
      "updatedAt": "2019-01-01T12:00:00.000Z"
    }
  }
}

HTTP Request

POST
/wallet/refund

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
userId body string Yes* n/a A user identifier (uuid).
userReference body string Yes* n/a A user external reference (case-sensitive string).
currency body string Yes n/a Currency code (3 or 4 characters).
amount body number Yes n/a Withdrawal (floating point value).
toAddress body string Yes n/a External wallet address to send refunds to.

* Either parameter is required (but not both)

Responses

Code Reason
200 Creating the refund request was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find the specified user/currency.
500 An unexpected error occurred and the request was unsuccessful.

Confirmations

Transactions sent to a user's address will only be marked as completed after a certain number of block confirmations. After reaching the configured number of confirmations the funds can be considered available for use by the user.

Retrieve Confirmation Requirements

curl -u username:password -X GET \
  http://127.0.0.1/wallet/confirmationRequirement?currency=BTC \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'GET',
  url: 'http://127.0.0.1/wallet/confirmationRequirement',
  qs: {
    currency: 'BTC'
  },
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "confirmationRequirement": [
      {
        "currency": "BTC",
        "maximumAmount": 0.125,
        "minimumConfirmations": 1,
        "updatedAt": "2019-01-01T12:00:00.000Z"
      },
      {
        "currency": "BTC",
        "maximumAmount": 0.25,
        "minimumConfirmations": 2,
        "updatedAt": "2019-01-01T12:00:00.000Z"
      },
      {
        "currency": "BTC",
        "maximumAmount": 0.5,
        "minimumConfirmations": 3,
        "updatedAt": "2019-01-01T12:00:00.000Z"
      },
      {
        "currency": "BTC",
        "maximumAmount": 1,
        "minimumConfirmations": 4,
        "updatedAt": "2019-01-01T12:00:00.000Z"
      },
      {
        "currency": "BTC",
        "maximumAmount": 2,
        "minimumConfirmations": 5,
        "updatedAt": "2019-01-01T12:00:00.000Z"
      },
      {
        "currency": "BTC",
        "maximumAmount": 4,
        "minimumConfirmations": 6,
        "updatedAt": "2019-01-01T12:00:00.000Z"
      }
    ]
  }
}

HTTP Request

GET
/wallet/confirmationRequirement

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
currency query string Yes n/a Currency code (3 or 4 characters).

Responses

Code Reason
200 Retrieving confirmation requirements was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find the specified tenant.
500 An unexpected error occurred and the request was unsuccessful.

Update Confirmation Requirements

When updating confirmation requirements the full list (default 6 entries) must be provided.

# To remove all confirmation requirements, send an empty array:
curl -u username:password -X PUT \
  http://127.0.0.1/wallet/confirmationRequirement \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "BTC",
    "confirmationRequirement": []
}'

# To update confirmation requirements:
curl -u username:password -X PUT \
  http://127.0.0.1/wallet/confirmationRequirement \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "BTC",
    "confirmationRequirement": [
        {
            "maximumAmount": 0.125,
            "minimumConfirmations": 1
        },
         {
            "maximumAmount": 0.25,
            "minimumConfirmations": 2
        },
         {
            "maximumAmount": 0.5,
            "minimumConfirmations": 3
        },
         {
            "maximumAmount": 1,
            "minimumConfirmations": 4
        },
         {
            "maximumAmount": 2,
            "minimumConfirmations": 5
        },
         {
            "maximumAmount": 4,
            "minimumConfirmations": 6
        }
    ]
}'
var request = require('request');

// To remove all confirmation requirements, send an empty array:
var confirmationRequirement = [];

// To update confirmation requirements:
confirmationRequirement = [
  {
    maximumAmount: 0.125,
    minimumConfirmations: 1
  },
  {
    maximumAmount: 0.25,
    minimumConfirmations: 2
  },
  {
    maximumAmount: 0.5,
    minimumConfirmations: 3
  },
  {
    maximumAmount: 1,
    minimumConfirmations: 4
  },
  {
    maximumAmount: 2,
    minimumConfirmations: 5
  },
  {
    maximumAmount: 4,
    minimumConfirmations: 6
  }
];

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'PUT',
  url: 'http://127.0.0.1/wallet/confirmationRequirement',
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd',
    'Content-Type': 'application/json'
  },
  body: {
    currency: 'BTC',
    confirmationRequirement: confirmationRequirement
  },
  json: true
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "confirmationRequirement": [
      {
        "maximumAmount": 0.125,
        "minimumConfirmations": 1,
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "currency": "BTC"
      },
      {
        "maximumAmount": 0.25,
        "minimumConfirmations": 2,
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "currency": "BTC"
      },
      {
        "maximumAmount": 0.5,
        "minimumConfirmations": 3,
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "currency": "BTC"
      },
      {
        "maximumAmount": 1,
        "minimumConfirmations": 4,
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "currency": "BTC"
      },
      {
        "maximumAmount": 2,
        "minimumConfirmations": 5,
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "currency": "BTC"
      },
      {
        "maximumAmount": 4,
        "minimumConfirmations": 6,
        "updatedAt": "2019-01-01T12:00:00.000Z",
        "currency": "BTC"
      }
    ]
  }
}

HTTP Request

PUT
/wallet/confirmationRequirement

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
currency body string Yes n/a Currency code (3 or 4 characters).
confirmationRequirement body array Yes n/a An array of objects with the keys "maximumAmount" and "minimumConfirmations". The values for these keys are numerical and must be distinct.

Responses

Code Reason
200 Updating confirmation requirements was successful.
400 Invalid request due to missing or incorrect parameters.
500 An unexpected error occurred and the request was unsuccessful.

Notifications

The application communicates stateful changes to various entities it tracks (deposits, withdrawals, refunds, wallets, etc) in an asynchronous manner by enqueuing notifications, which consumers may inspect and utilize as they see fit.

Topic Type Fired When Payload (body)
deposit.created Event Deposit has been received, but not confirmed.
{
  "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "amount": 0.12,
  "confirmations": 1,
  "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference": "PLR-7654-3210-8012-34567890abcd",
  "currencyId": 1,
  "currency": "BTC",
  "transactionTypeId": 2,
  "transactionTypeName": "Receive",
  "processStateId": 2,
  "processStateName": "Completed",
  "vout": 0
}
deposit.trusted Event Analysis of the deposit has been retrieved from a third-party service provider. The `trusted` field indicates whether the deposit may be spent before the transaction has been mined into a block (trusted=true) or the transaction is not yet considered spendable (trusted=false).
{
  "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "amount": 0.12,
  "confirmations": 0,
  "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference": "PLR-7654-3210-8012-34567890abcd",
  "currencyId": "1",
  "currency": "BTC",
  "transactionTypeId": "2",
  "transactionTypeName": "Receive",
  "processStateId": "7",
  "processStateName": "Monitoring",
  "trusted": true,
  "vout": 0
}
deposit.processed Event Deposit has been processed successfully.
{
  "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "amount": 0.12,
  "confirmations": 1,
  "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference": "PLR-7654-3210-8012-34567890abcd",
  "currencyId": 1,
  "currency": "BTC",
  "transactionTypeId": 2,
  "transactionTypeName": "Receive",
  "processStateId": 2,
  "processStateName": "Completed",
  "risk": "high",
  "vout": 0
}
withdraw.created Event Withdraw has been received, and is pending processing.
{
   "id": "65c8c5f0-1dfe-4b81-a206-b434bc2c31a5",
   "userId": "1234abcd-123a-4abc-8123-123456789abc",
   "userReference":"PLR-7654-3210-8012-34567890abcd",
   "currencyId": 1,
   "currency": "BTC",
   "amount": 0.25
}
withdraw.processed Event Withdraw has been processed successfully.
{
  "id": "65c8c5f0-1dfe-4b81-a206-b434bc2c31a5",
  "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "amount": 0.25,
  "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference": "PLR-7654-3210-8012-34567890abcd",
  "currencyId": 1,
  "fee": 0.002,
  "currency": "BTC",
  "transactionTypeId": 1,
  "transactionTypeName": "Send",
  "processStateId": 2,
  "processStateName": "Completed",
  "risk": "high"
}
refund.created Event Refund has been received, and is pending processing.
{
  "id": "65c8c5f0-1dfe-4b81-a206-b434bc2c31a5",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference":"PLR-7654-3210-8012-34567890abcd",
  "currencyId": 1,
  "currency": "BTC",
  "amount": 0.25
}
refund.processed Event Refund has been processed successfully.
{
  "id": "65c8c5f0-1dfe-4b81-a206-b434bc2c31a5",
  "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "amount": 0.25,
  "fee": 0.002,
  "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference": "PLR-7654-3210-8012-34567890abcd",
  "currencyId": 1,
  "currency": "BTC",
  "transactionTypeId": 7,
  "transactionTypeName": "Refund",
  "processStateId": 2,
  "processStateName": "Completed",
  "risk": "unavailable"
}
wallet.overflowed Event Wallet balance exceeds overflow thresholds. The "walletType" will be one of `receive`, `send`, `overflow`.
{
  "walletBalance": 1011.7996198,
  "excessBalance": 11.1996198,
  "walletType":"send",
  "walletName":"send"
}
wallet.withdrawn Event Portion of a wallet's balance has been sent to its configured overflow-wallet.
{
  "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "amount": 0.12,
  "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
  "userId": "1234abcd-123a-4abc-8123-123456789abc",
  "userReference": "PLR-7654-3210-8012-34567890abcd",
  "currencyId": 1,
  "currency": "BTC",
  "transactionTypeId": 1,
  "transactionTypeName": "Send",
  "processStateId": 2,
  "processStateName": "Completed",
  "risk": "unavailable"
}
wallet.underflowed Event Wallet balance shortfalls underflow thresholds. The "walletType" will be one of `receive`, `send`, `overflow`.
{
  "walletBalance": 1011.7996198,
  "balanceShortfall": -11.1996198,
  "walletType": "receive",
  "walletName": "receive"
}
config.error Event Configuration error.
{
  "error": "XYZ config seems to be invalid"
}
wallet.error Event Communication problem with wallet.
{
  "error": "error message"
}
wallet.error Event Insufficient funds in wallet.
{
  "error": "error message",
  "reason": "insufficient funds",
  "details": {
    walletName: 'send',
    currency: 'BTC',
    id: '1234abcd-123a-4abc-8123-123456789abc',
    walletBalance: 15,
    amountRequested: 16,
    raw: null
  }
}

Consumers

Consumers may interact with enqueued notifications by inspecting (i.e. "peek") them without marking them as consumed, as well as explicitly acknowledging (i.e. "ack") their consumption.

A consumer would typically adopt the following queue-consumption logic:

  1. "Peek" at one or more notifications every N seconds, starting at oldest-first.
  2. For each notification returned, process it.
  3. Mark the batch of notifications (the size determined in step #1) as "acknowledged".
  4. Repeat steps 1 through 3.

While this approach makes two calls to the notification-hosting system, it enables the consuming application to achieve fault-tolerance by only marking notifications as "complete" after being processed successfully.

Postback

The application can alternatively be configured to make an HTTP request to a postback URL. Please contact support to configure such URLs.

Configuring postback URLs will help the consumer to act upon some activity instead of continuously peeking new messages from an endpoint.

Structure

Every notification follows a singular format, and can be destructured to determine various information about the notification.

{
  "header": {
    "id": "a17e8c66-c9e8-4cad-91ae-058fdcc7c221",
    "type": "event",
    "topic": "entity.verb",
    "meta": {
      "tenantId": "620822e2-fa31-4bab-92ef-b3598e15278d"
    },
    "correlationId": "520822e2-fa31-4bab-92ef-b3598e15278d",
    "token": null,
    "version": "1.0.0",
    "timestamp": "2019-01-01T12:00:00.000Z"
  },
  "body": {
  }
}
Attribute Type Description
header object The notification "header" block. Contains information pertinent to the type of message, without details specific to the message.
header.id string A unique identifier for all notifications, in UUID v4 format.
header.type string The type of notification. One of "command", "event" or "request". External consumers need only be concerned with ever receiving notifications of type "event".
header.topic string A phrase indicating both the entity involved in the notification, and a verb indicating what happened, in "entity.verb" format.
header.meta* object A meta object block. Contains information for opted features
header.meta.tenantId* string A tenantId string, in UUID v4 format.
header.correlationId string A unique identifier linking two particular notifications together, in UUID v4 format. Only valid when type="request".
header.version string A version number specific to a particular combination of type and topic.
header.timestamp number A timestamp (UTC timezone, ISO 8601 format) representing the time that the notification was created.
body object The notification "body" block, whose contents are topic-specific.

* optional

Uniqueness

Uniqueness of notifications received either via polling or postback may be observed either by a notification's header "id" field, or (in the case of Bitcoin-related notifications) the union of txid, toAddress and vout.

Validation

In order to validate notification payload, keep below things in mind:

Validate Postback hashing

#verify SHA256 digest with Bash

PAYLOAD="${isoTime}${deterministicString}"
echo -n "${PAYLOAD}" | openssl dgst -sha256 -hmac "${PASSPHRASE}"



'use strict';

const crypto = require('crypto');
// package to convert object into Deterministic text
const  stringify  = require('json-stable-stringify');

/**
 format of data:
 {
  "header": {
    "id": "a17e8c66-c9e8-4cad-91ae-058fdcc7c221",
    "type": "event",
    "topic": "entity.verb",
    "meta": {
      "tenantId": "620822e2-fa31-4bab-92ef-b3598e15278d"
    },
    "correlationId": "520822e2-fa31-4bab-92ef-b3598e15278d",
    "token": null,
    "version": "1.0.0",
    "timestamp": "2019-01-01T12:00:00.000Z"
  },
  "body": {
  }
}
 */

function createDigest({
                        data,
                        algorithm,
                        passphrase,
                        timestamp,
                        digestFormat
                      }) {
  // ISO 8601 formatted string
  const isoTime = new Date(timestamp).toISOString();

  // Deterministic JSON-to-text
  const deterministicString = stringify(data);

  // One-way hash using ISO 8601 timestamp  + deterministicString
  return crypto
    .createHmac(algorithm, passphrase)
    .update(`${isoTime}${deterministicString}`)
    .digest(digestFormat)
    .toString();
}

If opted for postback hashing (HMAC message authentication) then a secret passphrase, an algorithm (e.g sha256, sha512), a header key (e.g Digest),and a format of hash (e.g. base64, hex) will be shared with you upon activation. Follow below steps to verify received hash

  1. convert header.timestamp to ISO 8601 (isoTime) formatted string
  2. Create Deterministic* JSON-to-text (deterministicString) of the payload object
  3. Create One-way hash using isoTime + deterministicString and using the passphrase in the shared format
  4. Compare generated hash with the one found in the header, if mismatched return an error code 400 with proper error message

Deterministic* string: We consider deterministic string means alphanumerically sort keys of JSON object before its stringification

Interact with Queued Messages

ENTITY=deposit; # one of the entities listed in the table 'Available Entities'
curl -u username:password -X POST \
  http://127.0.0.1/notifications/queue/$ENTITY \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'count=1&ack=true'
var request = require('request');
var entity = 'deposit'; // one of the entities listed in the table 'Available Entities'

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'POST',
  url: 'http://127.0.0.1/notifications/queue/' + entity,
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    count: 1,
    ack: true
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "count": 1,
    "deposit": [
      {
        "header": {
          "id": "a17e8c66-c9e8-4cad-91ae-058fdcc7c221",
          "type": "event",
          "topic": "deposit.processed",
          "correlationId": "520822e2-fa31-4bab-92ef-b3598e15278d",
          "token": null,
          "version": "1.0.0",
          "timestamp": "2019-01-01T12:00:00.000Z"
        },
        "body": {
          "txid": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
          "amount": 0.12,
          "confirmations": 1,
          "toAddress": "1abcdefghijklmnopqrstuvwzyzABCDEFG",
          "toAccountId": "fedcba98-7654-3210-8012-34567890abcd",
          "userReference": "PLR-7654-3210-8012-34567890abcd",
          "currency": "BTC",
          "transactionTypeId": 2,
          "processStateId": 1,
          "risk": "high"
        }
      }
    ]
  }
}

Inspection

To "peek" at messages in the queue, provide the value "false" to the parameter "ack".

Acknowledgement

To "acknowledge" messages in the queue, provide the value true to the parameter "ack". Note that this permanently removes enqueued messages.

HTTP Request

POST
/notifications/queue/{entity}

Note: While this endpoint may be used to obtain messages from a queue, it may also be used to alter the state of the queue; hence, its method is POST.

The {entity} parameter in the above URL must be replaced with any of the entity names listed in the table below.

Available Entities

Entity Related Verbs Limit Description
deposit created, processed 1,000,000 Users depositing funds into the system from an external source.
withdraw created, processed 1,000,000 Users withdrawing funds out of the system to an external source.
refund created, processed 100,000 Users refunding funds out of the system to an external source.
wallet overflowed, underflowed, withdrawn 10,000 Events related to monitoring and governing wallet balance.
config error 10,000 Events related to configuration errors.

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
count body number Yes n/a Controls the maximum number of messages to get. You may get fewer messages than this if the queue cannot immediately provide them.
ack body boolean No false Determines whether the messages will be removed from the queue. If ack is false (default) they will not be removed, if ack is true they will be removed.

Responses

Code Reason
200 Obtaining messages from the queue was successful.
400 Invalid request due to missing or incorrect parameters.
500 An unexpected error occurred and the request was unsuccessful.

Message Throttling

Events occur in the back-end which are often out of the application's control (blockchain synchronization, total number of transactions within a particular time-period, miner confirmation delays, etc).This can easily result in the consumer of notifications related to these kinds of events being inundated with notifications in a short period of time.

In order to mitigate this potential flood of notifications, the application will apply throttling to when it sends out certain notifications, such that if a number of the same types of notifications occur within a short period of time (e.g. 5-10 minutes), we will only send out a single notification indicating something has occurred.

An example would be two subsequent withdrawals which cause a wallet to experience a low-balance event. If two withdrawals are processed at the same time while a wallet balance is below an ideal low-water-mark, the application will send out a single "low wallet balance" notification.

Risk Analysis

To review information related to risk associated with user deposits and withdrawals, we expose certain third-party data via our API and event notifications. Additionally, in the unlikely event that third-party risk analysis services are temporarily unavailable, we facilitate re-evaluation of deposits and withdrawals via the API.

We perform risk analysis recording and verification on incoming deposit and outgoing withdraw activity to and from the wallets we manage according to configured parameters.

We also locally cache any results retrieved from third parties so they may be quickly inspected.

Finally, we establish the ability to pre-screen withdrawals, enabling API consumers to verify the destination address before committing a withdrawal transaction to the blockchain.

Workflow

Typical workflows are described below.

User ID vs. User Reference

As described in the Integration section, whichever mode by which you choose to refer to users (either by GBLPay Crypto's internal User ID, or by your own User Reference) will be reflected in all third-party risk-analysis data, to assist investigation efforts should the need arise.

Deposits

To observe risk related to deposits, a consumer of the API and event notifications should expect to implement the following workflow:

  1. You provide the user a deposit address using the POST /wallet/deposit API endpoint.
  2. User performs a deposit (using the address obtained from Step 1) using an external wallet or exchange.
  3. Blockchain synchronization occurs, and we watch for the deposit along with the required confirmations for the deposit's amount.
  4. We perform a risk assessment on the blockchain record and locally record the results.
  5. We send out a notification indicating a deposit has completed.
  6. You periodically poll our notification service for deposits via the POST /notifications/deposit API endpoint, looking for events with deposit.processed.

At this point the user may be permitted to spend deposited funds.

In the event of failure at Step 4, we also provide you with an API endpoint, PUT /wallet/risk, including the transaction's txid as the criteria, to trigger a repeat of steps 4-6. See below for API details.

Withdrawals

To verify risk associated with a user's withdrawal address, a consumer of the API and event notifications should expect to implement the following workflow:

  1. User provides you with a withdrawal address from an external wallet.
  2. You make a call to the PUT /wallet/risk API endpoint, including the user's withdrawal address as the criteria.
  3. We perform a risk assessment pre-screening on the withdraw address and provide you with the results.
  4. If the result of the risk assessment is acceptable, you may then perform a call to POST /wallet/withdraw.
  5. We transfer the required funds to the address provided.
  6. We register the withdrawal with risk analysis service to facilitate their ongoing observance of risk-related activity related to this address.
  7. After blockchain synchronization, the management interface for the user's external wallet will indicate receipt of the transfer.

Refunds

To verify risk associated with a user's refund address, a consumer of the API and event notifications should expect to implement the same workflow as described for withdrawals:

  1. User provides you with a refund address from an external wallet.
  2. You make a call to the PUT /wallet/risk API endpoint, including the user's refund address as the criteria.
  3. We perform a risk assessment pre-screening on the refund address and provide you with the results.
  4. If the result of the risk assessment is acceptable, you may then perform a call to POST /wallet/refund.
  5. We transfer the required funds to the address provided.
  6. After blockchain synchronization, the management interface for the user's external wallet will indicate receipt of the transfer.

Retrieve risk

curl -u username:password -X PUT \
  'http://127.0.0.1/wallet/risk?context=address&address=1abcdefghijklmnopqrstuvwzyzABCDEFG&userId=1234abcd-123a-4abc-8123-123456789abc&currency=BTC' \
  -H 'X-Tenant-Key: 01234567-890a-4cde-8012-34567890abcd'
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'PUT',
  url: 'http://127.0.0.1/wallet/risk',
  headers: {
    'X-Tenant-Key': '01234567-890a-4cde-8012-34567890abcd',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  form: {
    context: 'address',
    userId: '1234abcd-123a-4abc-8123-123456789abc', // alternatively, userReference may be used
    currency: 'BTC',
    address: '1abcdefghijklmnopqrstuvwzyzABCDEFG'
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "risk": "low"
  }
}

HTTP Request

PUT
/wallet/risk

Parameters

Parameter Location Type Required Default Description
X-Tenant-Key header string Yes n/a A tenant's key (uuid).
context body string Yes n/a The risk context. Available options: address.
address body string Yes1 n/a A valid wallet address to which the user wants to withdraw funds.
currency body string Yes n/a Currency code (3 or 4 characters).
userId body string Yes2 n/a A user identifier (uuid).
userReference body string Yes2 n/a A user external reference (case-sensitive string).

1 The address parameter is required in the request when the context is set to address.
2 Either one of userId or userReference must be included in the request, but not both.

Responses

Possible risk values

"risk" will be one of high, low, unknown (set by third-party risk analysis services) or unavailable (set by us in the event of an error getting risk from third-party risk analysis services).

Code Reason
200 Retrieving risk information was successful.
400 Invalid request due to missing or incorrect parameters.
404 Unable to find the specified tenant.
500 An unexpected error occurred and the request was unsuccessful.

Monitoring

The application has an optional feature, real-time transaction monitoring.

When disabled, the application relies solely on configured confirmation requirements to consider deposits as acceptable for funding a user's account.

When enabled and running, the application will verify the transaction with a third-party provider to determine the viability of spending the amount indicated in a transaction at the 0-confirmation stage. By observing an additional kind of notification, deposit.trusted, a consumer of these notifications may elect to enable spending before the transaction is officially committed to the blockchain, and before the first confirmation has occurred.

Sample Deposit Flow

A sample sequence of events follows:

  1. End-user is provided an Address to be used as a deposit address for their account.
  2. End-user commits a transfer to the blockchain using the Address from the previous step, and obtains a Hash for the Transaction.
  3. The new Transaction enters the memory pool.
  4. The application learns about the new Transaction in form of an untrusted transaction with 0 confirmations, and sends a deposit.created notification.
  5. The application begins monitoring the Transaction, and invokes a third-party API to verify whether that Transaction is guaranteed to be risk-free.
  6. If the third-party service indicates the transaction is not trusted yet (not visible in the mempool, or other indicators specific to the Transaction), the application will send out a deposit.trusted notification with trusted=false, and continue to monitor the Transaction. While uncommon, this situation must be observed in order to ensure deposits remain risk-free.
  7. Once the application receives acceptance of the Transaction (often within seconds, and well before a typical first confirmation occurs), the application sends out a deposit.trusted notification indicating trusted=true. At this point, the funds may be considered 'spendable' by the end-user.
  8. The application continues to monitor the Transaction; once it meets configured confirmation requirements, it sends a follow-up deposit.processed notification, and ceases monitoring the Transaction.

Note

In all cases, note that a deposit's uniqueness stems from the combination of its Transaction Hash and its destination Address. Deposits must only be processed once, either upon receipt of a deposit.trusted notification (in the event that real-time transaction monitoring is enabled and the message payload indicates the deposit is trustable) or upon receipt of a deposit.processed notification (in the event that this feature is not enabled, or the deposit is untrusted and then mined into a block).

Ensure to verify the uniqueness of a Transaction's Hash and Address together before funding an account.

Transaction Types

In the context of these APIs a transaction type is associated with a transaction behaviour (e.g. Send, Receive, Refund, etc) in the cryptocurrency network.

Retrieve Available Transaction Types

curl -u username:password -X GET \
  http://127.0.0.1/wallet/transactionTypes
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'GET',
  url: 'http://127.0.0.1/wallet/transactionTypes'
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "transactionTypes": [
      {
        "id": 1,
        "name": "Send"
      },
      {
        "id": 2,
        "name": "Receive"
      },
      {
        "id": 3,
        "name": "Generate"
      },
      {
        "id": 4,
        "name": "Immature"
      },
      {
        "id": 5,
        "name": "Orphan"
      },
      {
        "id": 6,
        "name": "Overflow"
      },
      {
        "id": 7,
        "name": "Refund"
      }
    ]
  }
}

Retrieves all available transaction types.

HTTP Request

GET
/wallet/transactionTypes

Parameters

n/a

Responses

Code Reason
200 Retrieving the transactionTypes was successful.
400 Invalid request due to missing or incorrect parameters.
500 An unexpected error occurred and the request was unsuccessful.

Process States

In the context of these APIs the process state indicates the current status of a transaction in our system (e.g. NotStarted, InProgress, Succeeded, etc).

Retrieve Available Process States

curl -u username:password -X GET \
  http://127.0.0.1/wallet/processStates
var request = require('request');

var options = {
  auth: {
    user: 'username',
    pass: 'password'
  },
  method: 'GET',
  url: 'http://127.0.0.1/wallet/processStates'
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});

The request above returns the following JSON response:

{
  "success": true,
  "data": {
    "processStates": [
      {
        "id": 1,
        "name": "NotStarted"
      },
      {
        "id": 2,
        "name": "InProgress"
      },
      {
        "id": 3,
        "name": "Succeeded"
      },
      {
        "id": 4,
        "name": "Failed"
      },
      {
        "id": 5,
        "name": "Cancelled"
      }
    ]
  }
}

Retrieves all available process states.

HTTP Request

GET
/wallet/processStates

Parameters

n/a

Responses

Code Reason
200 Retrieving the processStates was successful.
400 Invalid request due to missing or incorrect parameters.
500 An unexpected error occurred and the request was unsuccessful.