NAV
Raw Shell JavaScript Node.js PHP Rust

Introduction

The Catenis API is organized around REST. The API has predictable, resource-oriented URLs, and uses HTTP response status codes to indicate the outcome of an API method request.

It uses built-in HTTP features, like HTTP verbs and headers, which are understood by off-the-shelf HTTP clients. It supports cross-origin resource sharing, allowing you to securely interact with the Catenis API from a client-side web application — though you should never expose your API access secret in any public website's client-side code.

A JSON is returned in response to any API method request, even when an error takes place.

Environments

The Catenis API ver. 0.11 is available in the following environments.

Sandbox

This is a non-production environment that connects with the testnet Bitcoin network.

Base API URL

https://sandbox.catenis.io/api/0.11/

Basic concepts

Catenis entities

Virtual device

The virtual device — or some times simply referred to as device — is the fundamental entity that is used to interact with the Catenis system.

Each virtual device has a unique device ID, which is assigned by the system when a new virtual device is created.

Optionally, a virtual device can also be identified by an end user provided product unique ID.

Each virtual device also has a system assigned API access secret, which is used for authenticating the virtual device when making an API request.

An optional name can also be assigned to a virtual device. That name, however, only serves as a label and cannot be used to select or otherwise reference a specific virtual device.

Client

The client is the entity that maps to an end user. A client can have one or more virtual devices.

Like virtual devices, each client has a unique client ID, which is assigned by the system when a new client is created.

Each client is associated with a system provided user account. The client user account is used by the end user to access the system and do administrative tasks, like creating new virtual devices, and adding service credits.

Catenis node

The Catenis node is the entity used to aggregate the Catenis services for a specific region or user premises.

Catenis nodes are identified by their index. Currently, only one public, central Catenis node — referred to as the Catenis Hub node — is available. The Catenis Hub node has index 0.

Clients are defined within a given Catenis node. So, a Catenis node will typically have one or more clients.

Permission rights

Catenis provides a permission mechanism where a virtual device — the controlling device — can allow or deny other virtual devices — the controlled devices — to interact with it in a given predefined way. Such predefined controlled interactions are referred to as permission events.

Permission events

The following permission events are currently defined:

Event name Description
receive-notify-new-msg Receive notification of new message from a device
receive-notify-msg-read Receive notification of message read by a device
receive-notify-asset-of Receive notification of asset received for assets issued by a device
receive-notify-asset-from Receive notification of asset received from a device
receive-notify-confirm-asset-of Receive notification of confirmation of pending asset issued by a device
receive-notify-confirm-asset-from Receive notification of confirmation of pending asset transferred by a device
send-read-msg-confirm Send read message confirmation to a device
receive-msg Receive message from a device
disclose-main-props Disclose device's main properties (name, product unique ID) to a device
disclose-identity-info Disclose device's basic identification information to a device
receive-asset-of Receive an amount of an asset issued by a device
receive-asset-from Receive an amount of an asset from a device

A permission event is described as an action where the controlling device is the subject and the controlled device is the object of such action.

Thus, taking the receive-msg permission event as an example, if a device is given allow right in regards to that permission event, it means that the controlling device will be able to receive messages sent from that device. Otherwise — if a device is given deny right instead —, the controlling device shall not receive any messages sent from that device.

Permission levels

For a given pair of permission event and controlling device, the permission rights can be set at four different levels:

Permission right evaluation

For a given pair of permission event and controlling device, the effective permission right for a given (controlled) device is evaluated according to the following procedure:

  1. Starting at the device level, we check if the permission right for that (controlled) device is set. If it is set, this is the permission right that is in effect.

  2. Otherwise, we go to the level above, and check if the permission right for the client to which the (controlled) device belongs is set. If it is set, this is the permission right that is in effect.

  3. Otherwise, we go to the level above, and check if the permission right for the Catenis node where the client to which the (controlled) device belongs is defined is set. If it is set, this is the permission right that is in effect.

  4. Otherwise, whatever permission right that is set at the system level is what is in effect.

Authentication

General

Most Catenis API methods require authentication on each request. The authentication mechanism used is a SHA-256 Keyed-Hash Message Authentication Code (HMAC-SHA256). It is based on the AWS Signature version 4 authentication scheme, although it is not the same, and thus libraries that implement the AWS authentication scheme cannot be used with the Catenis API.

With HMAC-SHA256, the server and the client share a secret signing key. The signing key lives in the respective client application and is never transmitted across the line. Instead, the key is used to generate a hash for signing the message contents.

To authenticate and use the services provided by the Catenis API methods, one must have an active client account, and use one of their virtual devices to actually consume the service. The virtual device's device ID and API access secret are then used to generate the authentication token that needs to be sent with every request.

Public API methods

A few Catenis API methods are public and do not require any authentication. The end user can access these services by simply making a request to the API method's URL as he or she would normally do when accessing a Web page.

Unlike regular (private) API methods, public API methods are not called for a given virtual device. No virtual device is required, and the end user does not even need to have a Catenis client account.

Usage

To properly call a Catenis API method, the client application must authenticate the request before sending it, for which the following general steps must be taken:

  1. Constructs an HTTP request for the API method that needs to be called;
  2. Signs the request using the virtual device's API access secret;
  3. Adds an Authorization header containing, amongst other things, the virtual device's device ID and the calculated signature.

Alternatively, one of the supplied Catenis API client libraries can be used, which makes issuing and authenticating Catenis API requests much simpler.

Detailed specification

This section describes how to issue and authenticate an HTTP request that conforms with the Catenis HMAC-SHA256 authentication scheme used by the Catenis API.

HTTP headers

Not yet authenticated request (used in following examples):

POST /api/0.11/messages/log HTTP/1.1
Host: sandbox.catenis.io
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
X-BCoT-Timestamp: 20180127T121358Z
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 95

{"message":"This is only a test","options":{"encoding":"utf8","encrypt":true,"storage":"auto"}}

The HTTP request that needs to be authenticated must include at least the following HTTP headers, known as the essential headers:

Header Contents
Host The host name. Example: sandbox.catenis.io
X-BCoT-Timestamp The current UTC time in ISO 8601 format. Example: 20170125T000000Z

Aside from the essential headers, after the request is authenticated, it will include an HTTP Authorization header, since the authentication itself consists of adding that header to the request.

The following sections describe the elements that are needed for composing the contents of the Authorization header.

Conformed request

String literal:

  "POST\n/api/0.11/message/send\nhost:api.catenis.com\nx-bcot-timestamp:20180127T121358Z\n\n792cdbeef04dc33e8ebb4974070ec5a75bd1e3a6c5ef49b1c3ec1b87152694c6\n"

Printed text:

  POST
  api/0.11/message/send
  host:api.catenis.com
  x-bcot-timestamp:20180127T121358Z

  792cdbeef04dc33e8ebb4974070ec5a75bd1e3a6c5ef49b1c3ec1b87152694c6

The conformed request is defined as:

<http_verb> + "\n" + <api_endpoint_path> + "\n" + <essential_headers> + "\n" + <payload_hash> + "\n"

Where:

Term Description
<http_verb> The HTTP method of the request. One of: GET, POST, PUT, HEAD, or DELETE.
<api_endpoint_path> The complete path of the URL of the API method endpoint. Example: /api/0.11/message/send
<essential_headers> A list showing the essential headers with their respective contents. Each item is defined as: <header_name> + ":" + <header_contents> + "\n"; where <header_name> is the lowercase name of the header, and <header_contents> is the contents of the header. Example: host:sandbox.catenis.io\nx-bcot-timestamp:20170125T103246Z\n
<payload_hash> Defined as: HEX(SHA256(<payload>)); where <payload> is the payload (or body) of the HTTP request. If the request has no payload, an empty string should be used in its place.

String to sign

String literal:

  "CTN1-HMAC-SHA256\n20180127T121358Z\n20180127/ctn1_request\n6c5a53a5aed35fe4dc27146c7d01d548cd810b644b0dcada1d1416fe82cad6f0\n"

Printed text:

  CTN1-HMAC-SHA256
  20180127T121358Z
  20180127/ctn1_request
  6c5a53a5aed35fe4dc27146c7d01d548cd810b644b0dcada1d1416fe82cad6f0

The string to sign is defined as:

"CTN1-HMAC-SHA256" + "\n" + <timestamp> + "\n" + <scope> + "\n" + <conformed_request_hash> + "\n"

Where:

Term Description
<timestamp> Current UTC time in ISO 8601 format. Example: 20180127T121358Z
<scope> Defined as: <date> + “/ctn1_request”; where <date> is a date formatted as YYYYMMDD. Example: 20180127/ctn1_request
<conformed_request_hash> Defined as: HEX(SHA256(<conformed_request>)); where <conformed_request> is the conformed request element as defined in the Conformed request section above.

Signing key

String literal:

  "\xe9\x94\x04\xc8\xbb\xc2\x5d\x02\x56\xff\xa5\x8f\x6e\x72\x17\x9d\xe5\xdc\x7f\x67\xf9\xe5\x8f\x84\x32\xaf\x76\x18\xbb\xb7\x99\xe5"

The signing key is defined as:

HMAC-SHA256(<date_key>, “ctn1_request”)

Term Description
<date_key> Defined as: HMAC-SHA256(“CTN1" + <api_access_secret>, <scope_date>); where <api_access_secret> is the virtual device's API access secret, and <scope_date> is the <date> component of the <scope> element as defined in String to sign section above.

Signature

String literal:

  "70db4ecb53a69dfdc8dcef5934a4d12df93c14f3178fe7797261c4f66144a44b"

Printed text:

  70db4ecb53a69dfdc8dcef5934a4d12df93c14f3178fe7797261c4f66144a44b

The signature is defined as:

HEX(HMAC-SHA256(<signing_key>, <string_to_sign>))

Term Description
<signing_key> The signing key element as defined in the Signing key section above
<string_to_sign> The string to sign element as defined in the String to sign section above

Authorization header

Authenticated request:

POST /api/0.11/messages/log HTTP/1.1
Host: sandbox.catenis.io
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
X-BCoT-Timestamp: 20180127T121358Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180127/ctn1_request,Signature=70db4ecb53a69dfdc8dcef5934a4d12df93c14f3178fe7797261c4f66144a44b
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 95

{"message":"This is only a test","options":{"encoding":"utf8","encrypt":true,"storage":"auto"}}

The contents of the Authorization header is defined as:

"CTN1-HMAC-SHA256" + <space> + "Credential=" + <device_id> + "/" + <scope> + "," + "Signature=" + <signature>

Where:

Term Description
<space> A sequence of one or more whitespace characters.
<device_id> The virtual device's device ID. Example: dnN3Ea43bhMTHtTvpytS
<scope> The <scope> element as defined in the String to sign section above. Example: 20180127/ctn1_request
<signature> The signature element as defined in the Signature section above.
Status code Error message
401 Authorization failed; authorization value not well formed
Authorization failed; invalid device or signature
Authorization failed; missing required HTTP headers
Authorization failed; signature date not well formed
Authorization failed; signature date out of bounds
Authorization failed; timestamp not well formed
Authorization failed; timestamp not within acceptable time variation

Client libraries

To make it easier for developers to interact with the Catenis API and overcome the hurdles of authenticating each request, Blockchain of Things provide open-source client libraries for different programming languages and environments.

The following libraries are currently available:

Paw extensions

Aside from the Catenis API client libraries listed above, Blockchain of Things have also made available a set of customized Paw extensions that can be used to facilitate the creation and use of Catenis API requests from within Paw on a Mac, allowing for easy prototyping and testing of the Catenis API methods.

API methods

The following is a comprehensive list of the methods that comprise the Catenis API ver. 0.11.

Asset Export Outcome

Retrieve the current information about the outcome of an asset export.

Sample request:

GET /api/0.11/assets/aH2AkrrL55GcThhPNa3J/export/ethereum HTTP/1.1
X-BCoT-Timestamp: 20210810T195125Z
Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210810/ctn1_request, Signature=2d30b89906b459b0ebc5c5df6bf12b862b59851530a636c11320d2fd89c5614e
Host: localhost:3000
Connection: close
User-Agent: Paw/3.2.3 (Macintosh; OS X/11.5.0) GCDHTTPRequest
curl "http://localhost:3000/api/0.11/assets/aH2AkrrL55GcThhPNa3J/export/ethereum" \
     -H 'X-BCoT-Timestamp: 20210810T195231Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210810/ctn1_request, Signature=3fc5a2654f845c15b0fa731094e9ac8b7f0aa1b2f657580c162985e31d3b5438'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aH2AkrrL55GcThhPNa3J';
var foreignBlockchain = 'ethereum';

ctnApiClient.assetExportOutcome(assetId, foreignBlockchain, function(error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.status === 'success') {
            // Asset successfully exported
            console.log('Foreign token ID (address):', data.token.id);
        }
        else if (data.status === 'pending') {
            // Final asset export state not yet reached
        }
        else {
            // Asset export has failed. Process error
            console.error('Error executing foreign blockchain transaction:', data.foreignTransaction.error);
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aH2AkrrL55GcThhPNa3J';
var foreignBlockchain = 'ethereum';

ctnApiClient.assetExportOutcome(assetId, foreignBlockchain, function(error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.status === 'success') {
            // Asset successfully exported
            console.log('Foreign token ID (address):', data.token.id);
        }
        else if (data.status === 'pending') {
            // Final asset export state not yet reached
        }
        else {
            // Asset export has failed. Process error
            console.error('Error executing foreign blockchain transaction:', data.foreignTransaction.error);
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aH2AkrrL55GcThhPNa3J';
$foreignBlockchain = 'ethereum';

try {
    $data = $ctnApiClient->assetExportOutcome($assetId, $foreignBlockchain);

    // Process returned data
    if ($data->status === 'success') {
        // Asset successfully exported
        echo 'Foreign token ID (address): ' . $data->token->id . PHP_EOL;
    } elseif ($data->status === 'pending') {
        // Final asset export state not yet reached
    } else {
        // Asset export has failed. Process error
        echo 'Error executing foreign blockchain transaction: ' . $data->foreignTransaction->error . PHP_EOL;
    }
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aH2AkrrL55GcThhPNa3J";

    let result = ctn_client.asset_export_outcome(
        asset_id,
        ForeignBlockchain::Ethereum,
    )?;

    match result.status {
        AssetExportStatus::Success => {
            // Asset successfully exported
            println!("Foreign token ID (address): {}", result.token.id.unwrap());
        },
        AssetExportStatus::Pending => {
            // Final asset export state not yet reached
        },
        AssetExportStatus::Error => {
            // Asset export has failed. Process error
            println!(
                "Error executing foreign blockchain transaction: {}",
                result.foreign_transaction.error.unwrap()
            );
        },
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/:assetId/export/:foreignBlockchain

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "foreignTransaction": {
      "txid": "0x1f14474f441557056055a186ccf6839bd4dfce79e0b134d77084b6ef4274dc1a",
      "isPending": false,
      "success": true
    },
    "token": {
      "name": "Catenis test token #10",
      "symbol": "CTK10",
      "id": "0x537580164Ba9DB2e8C254a38E254ce15d07fDef9"
    },
    "status": "success",
    "date": "2021-08-03T18:41:27.679Z"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  foreignTransaction Object Information about the transaction issued on the foreign blockchain to create the resulting foreign token.
    txid String The ID (or hash) of the foreign blockchain transaction.
    isPending Boolean Indicates whether the foreign blockchain transaction is yet to be executed.
    success Boolean (only returned after the foreign blockchain transaction is executed) Indicates whether the foreign blockchain transaction has been successfully executed or not.
    error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
  token Object Information about the resulting foreign token.
    name String The token name.
    symbol String The token symbol.
    id String (only returned if the asset is successfully export) The ID (or address) of the token on the foreign blockchain.
  status String The current state of the asset export. One of: pending, success, or error
  date String ISO 8601 formatted date and time when the asset has been exported.

Possible errors

Status code Error message
400 Asset is not yet exported
Invalid asset ID
Invalid parameters: <param_list>
403 No permission to retrieve asset export outcome
500 Internal server error
503 System currently not available; please try again at a later time

Asset Migration Outcome

Retrieve the current information about the outcome of an asset migration.

Sample request:

GET /api/0.11/assets/migrations/gq8x3efLpEXTkGQchHTb HTTP/1.1
X-BCoT-Timestamp: 20210810T211045Z
Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210810/ctn1_request, Signature=60c4f0069c227fca8780ecb263cac1b98f40d15416a21c54cd6c1498644a7915
Host: localhost:3000
Connection: close
User-Agent: Paw/3.2.3 (Macintosh; OS X/11.5.0) GCDHTTPRequest
curl "http://localhost:3000/api/0.11/assets/migrations/gq8x3efLpEXTkGQchHTb" \
     -H 'X-BCoT-Timestamp: 20210810T211101Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210810/ctn1_request, Signature=97a742d0245a5b078bccaed62724d725826ba87d92ae0a6d160abe26ab0958af'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var migrationId = 'gq8x3efLpEXTkGQchHTb';

ctnApiClient.assetMigrationOutcome(migrationId, function(error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.status === 'success') {
            // Asset amount successfully migrated
            console.log('Asset amount successfully migrated');
        }
        else if (data.status === 'pending') {
            // Final asset migration state not yet reached
        }
        else {
            // Asset migration has failed. Process error
            if (data.catenisService.error) {
                console.error('Error executing Catenis service:', data.catenisService.error);
            }

            if (data.foreignTransaction.error) {
                console.error('Error executing foreign blockchain transaction:', data.foreignTransaction.error);
            }
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var migrationId = 'gq8x3efLpEXTkGQchHTb';

ctnApiClient.assetMigrationOutcome(migrationId, function(error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.status === 'success') {
            // Asset amount successfully migrated
            console.log('Asset amount successfully migrated');
        }
        else if (data.status === 'pending') {
            // Final asset migration state not yet reached
        }
        else {
            // Asset migration has failed. Process error
            if (data.catenisService.error) {
                console.error('Error executing Catenis service:', data.catenisService.error);
            }

            if (data.foreignTransaction.error) {
                console.error('Error executing foreign blockchain transaction:', data.foreignTransaction.error);
            }
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$migrationId = 'gq8x3efLpEXTkGQchHTb';

try {
    $data = $ctnApiClient->assetMigrationOutcome($migrationId);

    // Process returned data
    if ($data->status === 'success') {
        // Asset amount successfully migrated
        echo 'Asset amount successfully migrated' . PHP_EOL;
    } elseif ($data->status === 'pending') {
        // Final asset migration state not yet reached
    } else {
        // Asset migration has failed. Process error
        if (isset($data->catenisService->error)) {
            echo 'Error executing Catenis service: ' . $data->catenisService->error . PHP_EOL;
        }

        if (isset($data->foreignTransaction->error)) {
            echo 'Error executing foreign blockchain transaction: ' . $data->foreignTransaction->error . PHP_EOL;
        }
    }
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let migration_id = "gq8x3efLpEXTkGQchHTb";

    let result = ctn_client.asset_migration_outcome(
        migration_id,
    )?;

    match result.status {
        AssetMigrationStatus::Success => {
            // Asset amount successfully migrated
            println!("Asset amount successfully migrated");
        },
        AssetMigrationStatus::Pending => {
            // Final asset migration state not yet reached
        },
        _ => {
            // Asset migration has failed. Process error
            if let Some(error) = result.catenis_service.error {
                println!("Error executing Catenis service: {}", error);
            }

            if let Some(error) = result.foreign_transaction.error {
                println!("Error executing foreign blockchain transaction: {}", error);
            }
        },
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/migrations/:migrationId

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "assetId": "aH2AkrrL55GcThhPNa3J",
    "foreignBlockchain": "ethereum",
    "direction": "outward",
    "amount": 10,
    "catenisService": {
      "status": "fulfilled",
      "txid": "61fcb4feb64ecf3b39b4bb6d64eb9cc68a58ba1d892f981ef568d07b7aa11fdf"
    },
    "foreignTransaction": {
      "txid": "0x212ab54f136a6fc1deae9ec217ef2d0417615178777131e8bb6958447fd20fe7",
      "isPending": false,
      "success": true
    },
    "status": "success",
    "date": "2021-08-03T18:51:55.591Z"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  assetId String The ID of the asset the amount of which has been migrated.
  foreignBlockchain String The key identifying the foreign blockchain to/from where the asset amount has been migrated. One of: ethereum, binance, or polygon.
  direction String The direction of the migration. One of: outward or inward.
  amount Number The migrated asset amount.
  catenisService Object Information about the execution of the migrate asset Catenis service.
    status String The current state of the service's execution. One of: awaiting, failure, or fulfilled.
    txid String (only returned if the service is successfully fulfilled) The ID of the Catenis transaction issued to fulfill the service.
    error String (only returned if the service's execution has failed) An error message describing what went wrong when executing the service.
  foreignTransaction Object Information about the transaction issued on the foreign blockchain to mint/burn the amount of the foreign token.
    txid String The ID (or hash) of the foreign blockchain transaction.
    isPending Boolean Indicates whether the foreign blockchain transaction is yet to be executed.
    success Boolean (only returned after the foreign blockchain transaction is executed) Indicates whether the foreign blockchain transaction has been successfully executed or not.
    error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
  status String The current state of the asset migration. One of: pending, interrupted, success, or error.
  date String ISO 8601 formatted date and time when the asset amount has been migrated.

Possible errors

Status code Error message
400 Invalid asset migration ID
Invalid parameters: <param_list>
403 No permission to retrieve asset migration outcome
500 Internal server error
503 System currently not available; please try again at a later time

Check Effective Permission Right

Checks the effective permission right that is currently applied to a given virtual device for a specified permission event.

The virtual device issuing the request acts as the controlling device. Thus the permission right returned is for the pair composed of the permission event specified in the API request and the virtual device issuing the request.

Sample request:

GET /api/0.11/permission/events/receive-msg/rights/dv3htgvK7hjnKx3617Re HTTP/1.1
X-BCoT-Timestamp: 20180219T104640Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180219/ctn1_request, Signature=0753e60d70a02448386d6485ab6d7ca34b1faa851bf71b6219256ae5059dfa09
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/permission/events/receive-msg/rights/dv3htgvK7hjnKx3617Re" \
     -H 'X-BCoT-Timestamp: 20180219T104602Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180219/ctn1_request, Signature=521537ae60e0cc6099c459220702aad51d68c7c6d82328d6df3d3dc122de8683'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var checkDeviceId = 'dv3htgvK7hjnKx3617Re';

ctnApiClient.checkEffectivePermissionRight('receive_msg', checkDeviceId, false, function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        var deviceId = Object.keys(data)[0];

        console.log('Effective right for device', deviceId, ':', data[deviceId]);
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var checkDeviceId = 'dv3htgvK7hjnKx3617Re';

ctnApiClient.checkEffectivePermissionRight('receive_msg', checkDeviceId, false, function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        var deviceId = Object.keys(data)[0];

        console.log('Effective right for device', deviceId, ':', data[deviceId]);
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$checkDeviceId = 'dv3htgvK7hjnKx3617Re';

try {
    $data = $ctnApiClient->checkEffectivePermissionRight('receive-msg', $checkDeviceId);

    // Process returned data
    $deviceId = array_keys(get_object_vars($data))[0];
    echo 'Effective right for device ' . $deviceId . ': ' . $data->$deviceId . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let check_device = DeviceId {
        id: String::from("dv3htgvK7hjnKx3617Re"),
        is_prod_unique_id: None,
    };

    let result = ctn_client.check_effective_permission_right(
        PermissionEvent::ReceiveMsg,
        check_device,
    )?;

    let (device_id, right) = result.iter().next().unwrap();

    println!("Effective right for device {}: {:?}", device_id, right);

    Ok(())
}

Accessibility

Private

Request

GET /permission/events/:eventName/rights/:deviceId

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "dv3htgvK7hjnKx3617Re": "allow"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request. In this particular case, it is an object that works as a dictionary where its single property is the device ID of the device for which the effective permission right is being checked, and its value is the permission right itself.
  <check_device_ID> String The permission right that is currently in effective for the virtual device the device ID of which is this property's name.

Possible errors

Status code Error message
400 Invalid device
Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

Export Asset

Export an asset to a foreign blockchain, by creating a new (ERC-20 compliant) token on that blockchain.

Sample request:

POST /api/0.11/assets/aH2AkrrL55GcThhPNa3J/export/ethereum HTTP/1.1
X-BCoT-Timestamp: 20210809T144134Z
Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210809/ctn1_request, Signature=87ed19ecefc670d61d4d85c0da80b608fc102a060e45c3d5caa5057eefc33d13
Content-Type: application/json; charset=utf-8
Host: localhost:3000
Connection: close
User-Agent: Paw/3.2.3 (Macintosh; OS X/11.5.0) GCDHTTPRequest
Content-Length: 60

{"token":{"name":"Catenis test token #10","symbol":"CTK10"}}
curl -X "POST" "http://localhost:3000/api/0.11/assets/aH2AkrrL55GcThhPNa3J/export/ethereum" \
     -H 'X-BCoT-Timestamp: 20210809T144203Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210809/ctn1_request, Signature=989280734b7ebf40057ec305d02af8d2d899f78cddcfca1ff4d30c652a3b8dc6' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "token": {
    "name": "Catenis test token #10",
    "symbol": "CTK10"
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aH2AkrrL55GcThhPNa3J';
var foreignBlockchain = 'ethereum';

ctnApiClient.exportAsset(assetId, foreignBlockchain, {
    name: 'Catenis test token #10',
    symbol: 'CTK10'
}, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Pending asset export:', data);

        // Start polling for asset export outcome
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aH2AkrrL55GcThhPNa3J';
var foreignBlockchain = 'ethereum';

ctnApiClient.exportAsset(assetId, foreignBlockchain, {
    name: 'Catenis test token #10',
    symbol: 'CTK10'
}, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Pending asset export:', data);

        // Start polling for asset export outcome
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aH2AkrrL55GcThhPNa3J';
$foreignBlockchain = 'ethereum';

try {
    $data = $ctnApiClient->exportAsset($assetId, $foreignBlockchain, [
        'name' => 'Catenis test token #10',
        'symbol' => 'CTK10'
    ]);

    // Process returned data
    echo 'Pending asset export: ' . print_r($data, true);

    // Start polling for asset export outcome
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aH2AkrrL55GcThhPNa3J";

    let result = ctn_client.export_asset(
        asset_id,
        ForeignBlockchain::Ethereum,
        NewForeignTokenInfo {
            name: String::from("Catenis test token #10"),
            symbol: String::from("CTK10"),
        },
        None,
    )?;

    println!("Pending asset export: {:?}", result);

    // Start polling for asset export outcome

    Ok(())
}

Accessibility

Private

Request

POST /assets/:assetId/export/:foreignBlockchain

Parameters

A JSON containing the following properties:

Property Type Description
token Object
  name String The name of the token to be created on the foreign blockchain.
  symbol String The symbol of the token to be created on the foreign blockchain.
options Object (optional)
  consumptionProfile String (optional) Name of the foreign blockchain's native coin consumption profile to use. Valid options: fastest, fast, average, slow.
  estimateOnly Boolean (optional, default: false) When set, indicates that no asset export should be executed but only the estimated price (in the foreign blockchain's native coin) to fulfill the operation should be returned.

Sample response (regular export):

{
  "status": "success",
  "data": {
    "foreignTransaction": {
      "txid": "0x1f14474f441557056055a186ccf6839bd4dfce79e0b134d77084b6ef4274dc1a",
      "isPending": true
    },
    "token": {
      "name": "Catenis test token #10",
      "symbol": "CTK10"
    },
    "status": "pending",
    "date": "2021-08-03T18:41:11.781Z"
  }
}

Sample response (estimate only):

{
  "status": "success",
  "data": {
    "estimatedPrice": "0.05850782"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  foreignTransaction Object (not returned for estimate only) Information about the transaction issued on the foreign blockchain to create the resulting foreign token.
    txid String The ID (or hash) of the foreign blockchain transaction.
    isPending Boolean Indicates whether the foreign blockchain transaction is yet to be executed.
    success Boolean (only returned after the foreign blockchain transaction is executed) Indicates whether the foreign blockchain transaction has been successfully executed or not.
    error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
  token Object (not returned for estimate only) Information about the resulting foreign token.
    name String The token name.
    symbol String The token symbol.
    id String (only returned if the asset is successfully export) The ID (or address) of the token on the foreign blockchain.
  status String (not returned for estimate only) The current state of the asset export. One of: pending, success, or error.
  date String (not returned for estimate only) ISO 8601 formatted date and time when the asset has been exported.
  estimatedPrice String (only returned for estimate only) A text value representing the price, in the foreign blockchain's native coin, required to execute the foreign blockchain transaction.

Possible errors

Status code Error message
400 Asset already exported
Discarded concurrent foreign token smart contract call
Foreign blockchain funds not enough to cover transaction execution price (<value>)
Invalid asset ID
Invalid parameters: <param_list>
Unexpected error calling foreign token smart contract
403 No permission to export asset
500 Internal server error
503 System currently not available; please try again at a later time

Get Asset Balance

Gets the current balance of a given asset held by the device.

Sample request:

GET /api/0.11/assets/aQjlzShmrnEZeeYBZihc/balance HTTP/1.1
X-BCoT-Timestamp: 20180417T165555Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=0531b1ce00b03de1ca707db48fd2474328e21fdb6930b8661a4608e8fe735b84
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/assets/aQjlzShmrnEZeeYBZihc/balance" \
     -H 'X-BCoT-Timestamp: 20180417T165613Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=2f85718595bc2633e13b21315babeb00b60327b317e3c56dab3865f2aa29115c'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.getAssetBalance(assetId,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Current asset balance:', data.balance.total);
            console.log('Amount not yet confirmed:', data.balance.unconfirmed);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.getAssetBalance(assetId,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Current asset balance:', data.balance.total);
            console.log('Amount not yet confirmed:', data.balance.unconfirmed);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aQjlzShmrnEZeeYBZihc';

try {
    $data = $ctnApiClient->getAssetBalance($assetId);

    // Process returned data
    echo 'Current asset balance: ' . $data->balance->total . PHP_EOL;
    echo 'Amount not yet confirmed: ' . $data->balance->unconfirmed . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aQjlzShmrnEZeeYBZihc";

    let result = ctn_client.get_asset_balance(
        asset_id,
    )?;

    println!("Current asset balance: {}", result.total);
    println!("Amount not yet confirmed: {}", result.unconfirmed);

    Ok(())
}

Accessibility

Private

Request

GET /assets/:assetId/balance

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "total": 1145.75,
    "unconfirmed": 0
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  total Number The current balance of the asset held by the device that issues the request.
  unconfirmed Number The amount from the balance that is not yet confirmed.

Possible errors

Status code Error message
400 Invalid asset ID
Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

Issue Asset

Issues an amount of a new asset.

Sample request:

POST /api/0.11/assets/issue/ HTTP/1.1
X-BCoT-Timestamp: 20180416T192026Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180416/ctn1_request, Signature=ca4df849242d5b66c45d24c3dd2f8810f7063f4bf1df1555aa95d18405b7b5dd
Content-Type: application/json; charset=utf-8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
Content-Length: 114

{"assetInfo":{"name":"XYZ001","description":"Testing asset #1","canReissue":true,"decimalPlaces":2},"amount":1200}
curl -X "POST" "https://sandbox.catenis.io/api/0.11/assets/issue/" \
     -H 'X-BCoT-Timestamp: 20180416T191501Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180416/ctn1_request, Signature=fd75cb18eb60c6afa8c5be53dadf1937b08c131d39b20fce19badb285bdb79cc' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "amount": 1200,
  "assetInfo": {
    "decimalPlaces": 2,
    "name": "XYZ001",
    "description": "Testing asset #1",
    "canReissue": true
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.issueAsset({
        name: 'XYZ001'
        description: 'Testing asset #1'
        canReissue: true
        decimalPlaces: 2
    }, 1200.00, null,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('ID of newly issued asset:', data.assetId);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.issueAsset({
        name: 'XYZ001'
        description: 'Testing asset #1'
        canReissue: true
        decimalPlaces: 2
    }, 1200.00, null,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('ID of newly issued asset:', data.assetId);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->issueAsset([
        'name' => 'XYZ001',
        'description' => 'Testing asset #1',
        'canReissue' => true,
        'decimalPlaces' => 2
    ], 1200.00, null);

    // Process returned data
    echo 'ID of newly issued asset: ' . $data->assetId . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.issue_asset(
        NewAssetInfo {
            name: String::from("XYZ001"),
            description: Some(String::from("Testing asset #1'")),
            can_reissue: true,
            decimal_places: 2,
        },
        1_200.0,
        None,
    )?;

    println!("ID of newly issued asset: {}", result.asset_id);

    Ok(())
}

Accessibility

Private

Request

POST /assets/issue

Parameters

A JSON containing the following properties:

Property Type Description
assetInfo Object
  name String The name of the asset to create.
  description String (optional) A description of the asset to create.
  canReissue Boolean Indicates whether more units of this asset can be issued at another time.
  decimalPlaces Number The maximum number of decimal places that can be used to specify a fractional amount of this asset. Must be an integer value between 0 and 7.
amount Number The amount of asset to issue.
holdingDevice Object (optional) Virtual device for which the asset is issued and that shall hold the issued amount.
  id String The ID of the holding device. Should be a device ID unless isProdUniqueId is set.
  isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.

Sample response:

{
  "status": "success",
  "data": {
    "assetId": "aQjlzShmrnEZeeYBZihc"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  assetId String ID of the newly issued asset.

Possible errors

Status code Error message
400 Amount to issue is too large
Invalid holding device
Invalid parameters: <param_list>
Not enough credits to pay for issue asset service
403 No permission to assign issued asset to holding device
500 Internal server error
503 System currently not available; please try again at a later time

List Asset Holders

Retrieves a list of virtual devices that currently hold any amount of a given asset.

Sample request:

GET /api/0.11/assets/aQjlzShmrnEZeeYBZihc/holders?limit=200 HTTP/1.1
X-BCoT-Timestamp: 20180417T193524Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=2a5d3aa86d303ed552b408356ae30174f428fab8c377c1f203812ad0b036cfa4
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/assets/aQjlzShmrnEZeeYBZihc/holders?limit=200" \
     -H 'X-BCoT-Timestamp: 20180417T193542Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=57ba39226a41800f13f7c985aa6f1ccca98ce6817c15680090e9e18a0ade7e0b'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.listAssetHolders(assetId, 200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.assetHolders.forEach(function (assetHolder, idx) {
                if (assetHolder.holder) {
                    console.log('Asset holder #', idx + 1, ':');
                    console.log('  - device holding an amount of the asset:', assetHolder.holder);
                    console.log('  - amount of asset currently held by device:', assetHolder.balance.total);
                    console.log('  - amount not yet confirmed:', assetHolder.balance.unconfirmed);
                }
                else {
                    console.log('Migrated asset:');
                    console.log('  - total migrated amount:', assetHolder.balance.total);
                    console.log('  - amount not yet confirmed:', assetHolder.balance.unconfirmed);
                }
            });

            if (data.hasMore) {
                console.log('Not all asset holders have been returned');
            }
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.listAssetHolders(assetId, 200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.assetHolders.forEach(function (assetHolder, idx) {
                if (assetHolder.holder) {
                    console.log('Asset holder #', idx + 1, ':');
                    console.log('  - device holding an amount of the asset:', assetHolder.holder);
                    console.log('  - amount of asset currently held by device:', assetHolder.balance.total);
                    console.log('  - amount not yet confirmed:', assetHolder.balance.unconfirmed);
                }
                else {
                    console.log('Migrated asset:');
                    console.log('  - total migrated amount:', assetHolder.balance.total);
                    console.log('  - amount not yet confirmed:', assetHolder.balance.unconfirmed);
                }
            });

            if (data.hasMore) {
                console.log('Not all asset holders have been returned');
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aQjlzShmrnEZeeYBZihc';

try {
    $data = $ctnApiClient->listAssetHolders($assetId, 200, 0);

    // Process returned data
    forEach($data->assetHolders as $idx => $assetHolder) {
        if (isset($assetHolder->holder)) {
            echo 'Asset holder #' . ($idx + 1) . ':' . PHP_EOL;
            echo '  - device holding an amount of the asset: ' . print_r($assetHolder->holder, true);
            echo '  - amount of asset currently held by device: ' . $assetHolder->balance->total . PHP_EOL;
            echo '  - amount not yet confirmed: ' . $assetHolder->balance->unconfirmed . PHP_EOL;
        } else {
            echo 'Migrated asset:' . PHP_EOL;
            echo '  - total migrated amount: ' . $assetHolder->balance->total . PHP_EOL;
            echo '  - amount not yet confirmed: ' . $assetHolder->balance->unconfirmed . PHP_EOL;
        }
    }

    if ($data->hasMore) {
        echo 'Not all asset holders have been returned' . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aQjlzShmrnEZeeYBZihc";

    let result = ctn_client.list_asset_holders(
        asset_id,
        Some(200),
        Some(0),
    )?;

    for idx in 0..result.asset_holders.len() {
        let asset_holder = &result.asset_holders[idx];

        if let Some(holder) = &asset_holder.holder {
            println!("Asset holder #{}:", idx + 1);
            println!(" - device holding an amount of the asset: {:?}", holder);
            println!(" - amount of asset currently held by device: {}", asset_holder.balance.total);
            println!(" - amount not yet confirmed: {}", asset_holder.balance.unconfirmed);
        } else {
          println!("Migrated asset:");
          println!(" - total migrated amount: {}", asset_holder.balance.total);
          println!(" - amount not yet confirmed: {}", asset_holder.balance.unconfirmed);
        }
    }

    if result.has_more {
        println!("Not all asset holders have been returned");
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/:assetId/holders

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "assetHolders": [
      {
        "holder": {
          "deviceId": "dnN3Ea43bhMTHtTvpytS",
          "name": "deviceB",
          "prodUniqueId": "XYZABC001"
        },
        "balance": {
          "total": 1145.75,
          "unconfirmed": 0
        }
      },
      {
        "holder": {
          "deviceId": "dv3htgvK7hjnKx3617Re",
          "name": "Catenis device #1"
        },
        "balance": {
          "total": 504.25,
          "unconfirmed": 0
        }
      },
      {
        "migrated": true,
        "balance": {
          "total": 50,
          "unconfirmed": 0
        }
      }
    ],
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  assetHolders Array(Object) The list of asset holder entries returned.
    holder Object (not returned for the special entry reporting the migrated asset amount) The virtual device that holds an amount of the asset — the holding device.
      deviceId String The device ID of the holding device.
      name String (only returned if holding device has this data, and the virtual device issuing the request has the necessary permission right) The name of the holding device.
      prodUniqueId String (only returned if holding device has this data, and the virtual device issuing the request has the necessary permission right) The product unique ID of the holding device.
    migrated Boolean (only returned for the special entry reporting the migrated asset amount) The value true indicating that this is the special entry reporting the migrated asset amount.
    balance Object
      total Number The current balance of the asset held by this holding device or that had been migrated.
      unconfirmed Number The amount from the balance that is not yet confirmed.
  hasMore Boolean Indicates whether there are more entries that have not been included in the returned list.

Possible errors

Status code Error message
400 Invalid asset ID
Invalid parameters: <param_list>
403 No permission to list asset holders
500 Internal server error
503 System currently not available; please try again at a later time

List Asset Migrations

Retrieves a list of issued asset migrations that satisfy a given search criteria.

Sample request:

GET /api/0.11/assets/migrations?foreignBlockchain=ethereum&direction=outward&status=success&startDate=2021-08-01T00:00:00Z&limit=200&skip=0 HTTP/1.1
X-BCoT-Timestamp: 20210811T142016Z
Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210811/ctn1_request, Signature=100242f637f3230f54e94dfcc30f25af4abbdf5c34add071130da94d37574379
Host: localhost:3000
Connection: close
User-Agent: Paw/3.2.4 (Macintosh; OS X/11.5.0) GCDHTTPRequest
curl "http://localhost:3000/api/0.11/assets/migrations?foreignBlockchain=ethereum&direction=outward&status=success&startDate=2021-08-01T00:00:00Z&limit=200&skip=0" \
     -H 'X-BCoT-Timestamp: 20210811T142047Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210811/ctn1_request, Signature=418fa567d70d0d8ae0ea38a1bdf068362a8cbfe8ce4c3ecb15f028ea5506169e'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listAssetMigrations({
    foreignBlockchain: 'ethereum',
    direction: 'outward',
    status: 'success',
    startDate: new Date('2021-08-01')
}, 200, 0, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.assetMigrations.length > 0) {
            console.log('Returned asset migrations:', data.assetMigrations);

            if (data.hasMore) {
                console.log('Not all asset migrations have been returned');
            }
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listAssetMigrations({
    foreignBlockchain: 'ethereum',
    direction: 'outward',
    status: 'success',
    startDate: new Date('2021-08-01')
}, 200, 0, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.assetMigrations.length > 0) {
            console.log('Returned asset migrations:', data.assetMigrations);

            if (data.hasMore) {
                console.log('Not all asset migrations have been returned');
            }
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listAssetMigrations([
        'foreignBlockchain' => 'ethereum',
        'direction' => 'outward',
        'status' => 'success',
        'startDate' => new \DateTime('20210801T000000Z')
    ], 200, 0);

    // Process returned data
    if (count($data->assetMigrations) > 0) {
        echo 'Returned asset migrations: ' . print_r($data->assetMigrations, true);

        if ($data->hasMore) {
            echo 'Not all asset migrations have been returned' . PHP_EOL;
        }
    }
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_asset_migrations(
        Some(ListAssetMigrationsOptions {
            asset_id: None,
            foreign_blockchain: Some(ForeignBlockchain::Ethereum),
            direction: Some(AssetMigrationDirection::Outward),
            status: Some(vec![AssetMigrationStatus::Success]),
            negate_status: None,
            start_date: Some("2021-08-01T00:00:00Z".into()),
            end_date: None,
            limit: Some(200),
            skip: Some(0),
        }),
    )?;

    if result.asset_migrations.len() > 0 {
        println!("Returned asset migrations: {:?}", result.asset_migrations);

        if result.has_more {
            println!("Not all asset migrations have been returned");
        }
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/migrations

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "assetMigrations": [
      {
        "migrationId": "gSLb9FTdGxgSLufuNzhR",
        "assetId": "aH2AkrrL55GcThhPNa3J",
        "foreignBlockchain": "ethereum",
        "direction": "inward",
        "amount": 4,
        "catenisService": {
          "status": "fulfilled",
          "txid": "26d45a275447caf36e0fbcc32f880f37d3aadb37ddceccc39cd8972a7933e3f4"
        },
        "foreignTransaction": {
          "txid": "0x883a4d9e02713b177fdd26b33e871dc765db3c964f2b1ef8e6f97eca24d718ee",
          "isPending": false,
          "success": true
        },
        "status": "success",
        "date": "2021-08-03T19:11:27.804Z"
      },
      {
        "migrationId": "gTQ8Qf5W6kdmdYdEEoD9",
        "assetId": "aCSy24HLjKMbpnvJ8GTx",
        "foreignBlockchain": "ethereum",
        "direction": "outward",
        "amount": 5,
        "catenisService": {
          "status": "fulfilled",
          "txid": "7d6a20ee009ad2bcbf5c799ee4eac594e4447bdb5007250f8ba038de97f63777"
        },
        "foreignTransaction": {
          "txid": "0x92fb47432e50b623441bb3b55dd65bf879183f87ea4913a16e75503c98792df9",
          "isPending": false,
          "success": true
        },
        "status": "success",
        "date": "2021-08-10T13:00:08.656Z"
      }
    ],
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  assetMigrations Array(Object) The returned list of issued asset migrations that satisfy the search criteria. The list is sorted in ascending order in regard to the returned date field.
    migrationId String The ID of the asset migration.
    assetId String The ID of the asset the amount of which has been migrated.
    foreignBlockchain String The key identifying the foreign blockchain to/from where the asset amount has been migrated. One of: ethereum, binance, or polygon.
    direction String The direction of the migration. One of: outward or inward.
    amount Number The migrated asset amount.
    catenisService Object Information about the execution of the migrate asset Catenis service.
      status String The current state of the service's execution. One of: awaiting, failure, or fulfilled.
      txid String (only returned if the service is successfully fulfilled) The ID of the Catenis transaction issued to fulfill the service.
      error String (only returned if the service's execution has failed) An error message describing what went wrong when executing the service.
    foreignTransaction Object Information about the transaction issued on the foreign blockchain to mint/burn the amount of the foreign token.
      txid String The ID (or hash) of the foreign blockchain transaction.
      isPending Boolean Indicates whether the foreign blockchain transaction is yet to be executed.
      success Boolean Indicates whether the foreign blockchain transaction has been successfully executed or not.
      error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
    status String The current state of the asset migration. One of: pending, interrupted, success, or error.
    date String ISO 8601 formatted date and time when the asset amount has been migrated.
  hasMore Boolean Indicates whether there are more asset migrations that satisfy the search criteria yet to be returned.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

List Exported Assets

Retrieves a list of issued asset exports that satisfy a given search criteria.

Sample request:

GET /api/0.11/assets/exported?foreignBlockchain=ethereum&status=success&startDate=2021-08-01T00:00:00Z&limit=200&skip=0 HTTP/1.1
X-BCoT-Timestamp: 20210811T115512Z
Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210811/ctn1_request, Signature=34abef10e2e75e8a3c2f66f1b40d50a2cb2e6f88ff7baff8e8fbd983a29d1c4b
Host: localhost:3000
Connection: close
User-Agent: Paw/3.2.3 (Macintosh; OS X/11.5.0) GCDHTTPRequest
curl "http://localhost:3000/api/0.11/assets/exported?foreignBlockchain=ethereum&status=success&startDate=2021-08-01T00:00:00Z&limit=200&skip=0" \
     -H 'X-BCoT-Timestamp: 20210811T115534Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210811/ctn1_request, Signature=258e511f7272407ba344922c0d68a63388018e70bcc2885acf343c415f0caf36'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listExportedAssets({
    foreignBlockchain: 'ethereum',
    status: 'success',
    startDate: new Date('2021-08-01')
}, 200, 0, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.exportedAssets.length > 0) {
            console.log('Returned asset exports:', data.exportedAssets);

            if (data.hasMore) {
                console.log('Not all asset exports have been returned');
            }
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listExportedAssets({
    foreignBlockchain: 'ethereum',
    status: 'success',
    startDate: new Date('2021-08-01')
}, 200, 0, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        if (data.exportedAssets.length > 0) {
            console.log('Returned asset exports:', data.exportedAssets);

            if (data.hasMore) {
                console.log('Not all asset exports have been returned');
            }
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listExportedAssets([
        'foreignBlockchain' => 'ethereum',
        'status' => 'success',
        'startDate' => new \DateTime('20210801T000000Z')
    ], 200, 0);

    // Process returned data
    if (count($data->exportedAssets) > 0) {
        echo 'Returned asset exports: ' . print_r($data->exportedAssets, true);

        if ($data->hasMore) {
            echo 'Not all asset exports have been returned' . PHP_EOL;
        }
    }
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_exported_assets(
        Some(ListExportedAssetsOptions {
            asset_id: None,
            foreign_blockchain: Some(ForeignBlockchain::Ethereum),
            token_symbol: None,
            status: Some(vec![AssetExportStatus::Success]),
            negate_status: None,
            start_date: Some("2021-08-01T00:00:00Z".into()),
            end_date: None,
            limit: Some(200),
            skip: Some(0),
        }),
    )?;

    if result.exported_assets.len() > 0 {
        println!("Returned asset exports: {:?}", result.exported_assets);

        if result.has_more {
            println!("Not all asset exports have been returned");
        }
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/exported

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "exportedAssets": [
      {
        "assetId": "aH2AkrrL55GcThhPNa3J",
        "foreignBlockchain": "ethereum",
        "foreignTransaction": {
          "txid": "0x1f14474f441557056055a186ccf6839bd4dfce79e0b134d77084b6ef4274dc1a",
          "isPending": false,
          "success": true
        },
        "token": {
          "name": "Catenis test token #10",
          "symbol": "CTK10",
          "id": "0x537580164Ba9DB2e8C254a38E254ce15d07fDef9"
        },
        "status": "success",
        "date": "2021-08-03T18:41:27.679Z"
      },
      {
        "assetId": "aCSy24HLjKMbpnvJ8GTx",
        "foreignBlockchain": "ethereum",
        "foreignTransaction": {
          "txid": "0x6299c35ccfa803ab0cb043e8d8ae4be8d7f3432d85f288ebb81e4d624e566b0a",
          "isPending": false,
          "success": true
        },
        "token": {
          "name": "Catenis test token #11",
          "symbol": "CTK11",
          "id": "0x5cE78E7204DD8f7d86142fAaA694d5354b997600"
        },
        "status": "success",
        "date": "2021-08-10T12:57:24.217Z"
      }
    ],
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  exportedAssets Array(Object) The returned list of issued asset exports that satisfy the search criteria. The list is sorted in ascending order in regard to the returned date field.
    assetId String The ID of the exported asset.
    foreignBlockchain String The key identifying the foreign blockchain to where the asset has been exported. One of: ethereum, binance, or polygon.
    foreignTransaction Object Information about the transaction issued on the foreign blockchain to create the resulting foreign token.
      txid String The ID (or hash) of the foreign blockchain transaction.
      isPending Boolean Indicates whether the foreign blockchain transaction is yet to be executed.
      success Boolean (only returned after the foreign blockchain transaction is executed) Indicates whether the foreign blockchain transaction has been successfully executed or not.
      error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
    token Object Information about the resulting foreign token.
      name String The token name.
      symbol String The token symbol.
      id String (only returned if the asset is successfully export) The ID (or address) of the token on the foreign blockchain.
    status String The current state of the asset export. One of: pending, success, or error
    date String ISO 8601 formatted date and time when the asset has been exported.
  hasMore Boolean Indicates whether there are more asset exports that satisfy the search criteria yet to be returned.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

List Issued Assets

Retrieves a list of assets that have been issued by the device.

Sample request:

GET /api/0.11/assets/issued?limit=200 HTTP/1.1
X-BCoT-Timestamp: 20180417T193403Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=ba41de81d939995b7cf76c03a4bc5861bf2176b7622348648c64fbb6f38dbc3a
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/assets/issued?limit=200" \
     -H 'X-BCoT-Timestamp: 20180417T193421Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=eb1e37742272ef732dae3d85cd0d75b32731b6d85d20d501d7969d55ca998849'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listIssuedAssets(200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.issuedAssets.forEach(function (issuedAsset, idx) {
                console.log('Issued asset #', idx + 1, ':');
                console.log('  - asset ID:', issuedAsset.assetId);
                console.log('  - total existent balance:', issuedAsset.totalExistentBalance);
            });

            if (data.hasMore) {
                console.log('Not all issued assets have been returned');
            }
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listIssuedAssets(200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.issuedAssets.forEach(function (issuedAsset, idx) {
                console.log('Issued asset #', idx + 1, ':');
                console.log('  - asset ID:', issuedAsset.assetId);
                console.log('  - total existent balance:', issuedAsset.totalExistentBalance);
            });

            if (data.hasMore) {
                console.log('Not all issued assets have been returned');
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listIssuedAssets(200, 0);

    // Process returned data
    forEach($data->issuedAssets as $idx => $issuedAsset) {
        echo 'Issued asset #' . ($idx + 1) . ':' . PHP_EOL;
        echo '  - asset ID: ' . $issuedAsset->assetId . PHP_EOL;
        echo '  - total existent balance: ' . $issuedAsset->totalExistentBalance . PHP_EOL;
    }

    if ($data->hasMore) {
        echo 'Not all issued assets have been returned' . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_issued_assets(
        Some(200),
        Some(0),
    )?;

    for idx in 0..result.issued_assets.len() {
        let issued_asset = &result.issued_assets[idx];

        println!("Issued asset #{}:", idx + 1);
        println!(" - asset ID: {}", issued_asset.asset_id);
        println!(" - total existent balance: {}", issued_asset.total_existent_balance);
    }

    if result.has_more {
        println!("Not all issued assets have been returned");
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/issued

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "issuedAssets": [
      {
        "assetId": "aQjlzShmrnEZeeYBZihc",
        "totalExistentBalance": 1650
      }
    ],
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  issuedAssets Array(Object) The list of issued asset entries returned.
    assetId String The ID of the asset.
    totalExistentBalance Number The current total balance of that asset in existence.
  hasMore Boolean Indicates whether there are more entries that have not been included in the returned list.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

List Messages

Retrieves a list of message entries that satisfy a given search criteria.

A virtual device can use it to identify newly received messages, for instance.

Sample request:

GET /api/0.11/messages?action=send&direction=inbound&fromDeviceIds=dv3htgvK7hjnKx3617Re&readState=unread&startDate=2018-01-01T00:00:00Z&endDate=2018-02-28T23:59:59Z&limit=200&skip=0 HTTP/1.1
X-BCoT-Timestamp: 20180216T135036Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180216/ctn1_request, Signature=bb8a7853798df41e6f9af1a900da4c3cecc161265ec85649f8b883678e8993ed
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/messages?action=send&direction=inbound&fromDeviceIds=dv3htgvK7hjnKx3617Re&readState=unread&startDate=2018-01-01T00:00:00Z&endDate=2018-02-28T23:59:59Z&limit=200&skip=0" \
     -H 'X-BCoT-Timestamp: 20180216T135101Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180216/ctn1_request, Signature=c0bb81382db103e30859056646bfa17759e9e8f73778abc0245fdbdb54be4656'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listMessages({
        action: 'send',
        direction: 'inbound',
        fromDevices: [{
            id: 'dv3htgvK7hjnKx3617Re'
        }],
        readState: 'unread',
        startDate: '20180101T000000Z',
        endDate: '20180228T235959Z'
    }, 200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            if (data.msgCount > 0) {
                console.log('Returned messages:', data.messages);

                if (data.hasMore) {
                    console.log('Not all messages have been returned');
                }
            }
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listMessages({
        action: 'send',
        direction: 'inbound',
        fromDevices: [{
            id: 'dv3htgvK7hjnKx3617Re'
        }],
        readState: 'unread',
        startDate: '20180101T000000Z',
        endDate: '20180228T235959Z'
    }, 200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            if (data.msgCount > 0) {
                console.log('Returned messages:', data.messages);

                if (data.hasMore) {
                    console.log('Not all messages have been returned');
                }
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listMessages([
        'action' => 'send',
        'direction' => 'inbound',
        'fromDevices' => [[
            'id' => 'dv3htgvK7hjnKx3617Re'
        ]],
        'readState' => 'unread',
        'startDate' => '20180101T000000Z',
        'endDate' => '20180228T235959Z'
    ], 200, 0);

    // Process returned data
    if ($data->msgCount > 0) {
        echo 'Returned messages: ' . print_r($data->messages, true);

        if ($data->hasMore) {
            echo 'Not all messages have been returned' . PHP_EOL;
        }
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_messages(
        Some(ListMessagesOptions {
            action: Some(MessageActionOption::Send),
            direction: Some(MessageDirectionOption::Inbound),
            from_devices: Some(vec![
                DeviceId {
                    id: String::from("dv3htgvK7hjnKx3617Re"),
                    is_prod_unique_id: None,
                },
            ]),
            to_devices: None,
            read_state: Some(MessageReadStateOption::Unread),
            start_date: Some("2018-01-01T00:00:00Z".into()),
            end_date: Some("2018-02-28T23:59:59Z".into()),
            limit: Some(200),
            skip: Some(0),
        }),
    )?;

    if result.msg_count > 0 {
        println!("Returned messages: {:?}", result.messages);

        if result.has_more {
            println!("Not all messages have been returned");
        }
    }

    Ok(())
}

Accessibility

Private

Request

GET /messages

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "messages": [
      {
        "messageId": "mospScAtxyX8ytD9Cq58",
        "action": "log",
        "read": false,
        "date": "2018-01-29T23:25:47.865Z"
      },
      {
        "messageId": "mNEWqgSMAeDAmBAkBDWr",
        "action": "send",
        "direction": "outbound",
        "to": {
          "deviceId": "dv3htgvK7hjnKx3617Re",
          "name": "Catenis device #1"
        },
        "readConfirmationEnabled": true,
        "read": true,
        "date": "2018-01-29T23:27:39.331Z"
      }
    ],
    "msgCount": 2,
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  messages Array(Object) The returned list of message information entries including the messages that satisfy the search criteria. The list is sorted in ascending order in regard to the returned date field.
    messageId String The ID of the message.
    action String Action originally performed on the message. Possible values: log, send. The value log indicates that this is a logged message, and the value send indicates that this is a sent message.
    direction String (only returned for sent messages) The direction of the sent message. Possible values: inbound, outbound. The value inbound indicates that this is a message received by the virtual device issuing the request, and the value outbound indicates that this is a message sent by the device issuing the request.
    from Object (only returned for sent messages) Identifies the virtual device that sent the message — the origin device.
      deviceId String The device ID of the origin device.
      name String (only returned if origin device has this data, and the device issuing the request has the necessary permission right) The name of the origin device.
      prodUniqueId String (only returned if origin device has this data, and the device issuing the request has the necessary permission right) The product unique ID of the origin device.
    to Object (only returned for sent messages) Identifies the device to which the message had been sent — the target device.
      deviceId String The device ID of the target device.
      name String (only returned if target device has this data, and the device issuing the request has the necessary permission right) The name of the target device.
      prodUniqueId String (only returned if target device has this data, and the device issuing the request has the necessary permission right) The product unique ID of the target device.
    readConfirmationEnabled Boolean (only returned for outbound sent messages) Indicates whether message had been sent with read confirmation enabled.
    read Boolean (not returned for outbound sent messages sent with read confirmation not enabled) Indicates whether the message had already been read.
    date String ISO 8601 formatted date and time when the message had been: logged, for logged message; sent, for outbound sent message; and received, for inbound sent message.
  msgCount Number Number of messages for which information was returned.
  hasMore Boolean Indicates whether there are more messages that satisfy the search criteria yet to be returned.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

List Notification Events

Retrieves a list of all system defined notification events.

Sample request:

GET /api/0.11/notification/events HTTP/1.1
X-BCoT-Timestamp: 20180219T160411Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180219/ctn1_request, Signature=02e8f56a46e2ea8001f94fac04115749606deacd5eee6f553b6d69c5d45ce553
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/notification/events" \
     -H 'X-BCoT-Timestamp: 20180219T160346Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180219/ctn1_request, Signature=7b717edae1c2c60721e2f74d02feb286a2275f615c930d86f5ea9954214bdfaf'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listNotificationEvents(function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        Object.keys(data).forEach(function (eventName) {
            console.log('Event name:', eventName, '; event description:', data[eventName]);
        });
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listNotificationEvents(function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        Object.keys(data).forEach(function (eventName) {
            console.log('Event name:', eventName, '; event description:', data[eventName]);
        });
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listNotificationEvents();

    // Process returned data
    forEach($data as $eventName => $description) {
        echo 'Event name: ' . $eventName . '; event description: ' . $description . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_notification_events()?;

    for (event, description) in result {
        println!("Event name: {}; event description: {}", event.to_string(), description);
    }

    Ok(())
}

Accessibility

Private

Request

GET /notification/events

Parameters

This request does not take any parameters.

Sample response:

{
  "status": "success",
  "data": {
    "new-msg-received": "A new message has been received",
    "sent-msg-read": "Previously sent message has been read by intended receiver (target device)"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request. In this particular case, it is an object that works as a dictionary where its properties are the notification event names, and their respective values the notification event description.
  <event_name> String The description of the notification event whose name is this property's name.

Possible errors

Status code Error message
500 Internal server error
503 System currently not available; please try again at a later time

List Owned Assets

Retrieves a list of assets that are currently held by the device.

Sample request:

GET /api/0.11/assets/owned?limit=200 HTTP/1.1
X-BCoT-Timestamp: 20180417T193253Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=e1986d68550fe45536e407ec0eba3d0104579106f3486b9aec652ac0f78add43
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/assets/owned?limit=200" \
     -H 'X-BCoT-Timestamp: 20180417T193325Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=2c6c8a066e7e983ad059854a3209ae7cfd024f1be504d51b5939fc3780dce8ae'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listOwnedAssets(200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.ownedAssets.forEach(function (ownedAsset, idx) {
                console.log('Owned asset #', idx + 1, ':');
                console.log('  - asset ID:', ownedAsset.assetId);
                console.log('  - current asset balance:', ownedAsset.balance.total);
                console.log('  - amount not yet confirmed:', ownedAsset.balance.unconfirmed);
            });

            if (data.hasMore) {
                console.log('Not all owned assets have been returned');
            }
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listOwnedAssets(200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.ownedAssets.forEach(function (ownedAsset, idx) {
                console.log('Owned asset #', idx + 1, ':');
                console.log('  - asset ID:', ownedAsset.assetId);
                console.log('  - current asset balance:', ownedAsset.balance.total);
                console.log('  - amount not yet confirmed:', ownedAsset.balance.unconfirmed);
            });

            if (data.hasMore) {
                console.log('Not all owned assets have been returned');
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listOwnedAssets(200, 0);

    // Process returned data
    foreach ($data->ownedAssets as $idx => $ownedAsset) {
        echo 'Owned asset #' . ($idx + 1) . ':' . PHP_EOL;
        echo '  - asset ID: ' . $ownedAsset->assetId . PHP_EOL;
        echo '  - current asset balance: ' . $ownedAsset->balance->total . PHP_EOL;
        echo '  - amount not yet confirmed: ' . $ownedAsset->balance->unconfirmed . PHP_EOL;
    }

    if ($data->hasMore) {
        echo 'Not all owned assets have been returned' . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_owned_assets(
        Some(200),
        Some(0),
    )?;

    for idx in 0..result.owned_assets.len() {
        let owned_asset = &result.owned_assets[idx];

        println!("Owned asset #{}:", idx + 1);
        println!(" - asset ID: {}", owned_asset.asset_id);
        println!(" - current asset balance: {}", owned_asset.balance.total);
        println!(" - amount not yet confirmed: {}", owned_asset.balance.unconfirmed);
    }

    if result.has_more {
        println!("Not all owned assets have been returned");
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/owned

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "ownedAssets": [
      {
        "assetId": "aQjlzShmrnEZeeYBZihc",
        "balance": {
          "total": 1145.75,
          "unconfirmed": 0
        }
      },
      {
        "assetId": "asEKmm6pdJomwmajghDy",
        "balance": {
          "total": 300000,
          "unconfirmed": 0
        }
      }
    ],
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  ownedAssets Array(Object) The list of owned asset entries returned.
    assetId String The ID of the asset.
    balance Object
      total Number The current balance of that asset held by the device that issues the request.
      unconfirmed Number The amount from the balance that is not yet confirmed.
  hasMore Boolean Indicates whether there are more entries that have not been included in the returned list.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

List Permission Events

Retrieves a list of all system defined permission events.

Sample request:

GET /api/0.11/permission/events HTTP/1.1
X-BCoT-Timestamp: 20180217T165054Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180217/ctn1_request, Signature=138e50e836dec8c78d48a46bd04c03434ff994b2cf59d929dff324e958f2c096
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/permission/events" \
     -H 'X-BCoT-Timestamp: 20180217T170003Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180217/ctn1_request, Signature=d1f7556572b5f038563e997644a9682690c87fab6388ccbb16221ab4b72b3a56'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listPermissionEvents(function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        Object.keys(data).forEach(function (eventName) {
            console.log('Event name:', eventName, '; event description:', data[eventName]);
        });
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.listPermissionEvents(function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        Object.keys(data).forEach(function (eventName) {
            console.log('Event name:', eventName, '; event description:', data[eventName]);
        });
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->listPermissionEvents();

    // Process returned data
    forEach($data as $eventName => $description) {
        echo 'Event name: ' . $eventName . '; event description: ' . $description . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.list_permission_events()?;

    for (event, description) in result {
        println!("Event name: {}; event description: {}", event.to_string(), description);
    }

    Ok(())
}

Accessibility

Private

Request

GET /permission/events

Parameters

This request does not take any parameters.

Sample response:

{
  "status": "success",
  "data": {
    "receive-notify-new-msg": "Receive notification of new message from a device",
    "receive-notify-msg-read": "Receive notification of message read by a device",
    "send-read-msg-confirm": "Send read message confirmation to a device",
    "receive-msg": "Receive message from a device",
    "disclose-main-props": "Disclose device's main properties (name, product unique ID) to a device",
    "disclose-identity-info": "Disclose device's basic identification information to a device"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request. In this particular case, it is an object that works as a dictionary where its properties are the permission event names, and their respective values the permission event description.
  <event_name> String The description of the permission event whose name is this property's name.

Possible errors

Status code Error message
500 Internal server error
503 System currently not available; please try again at a later time

Log Message

Records a message on the blockchain.

Sample request:

POST /api/0.11/messages/log HTTP/1.1
X-BCoT-Timestamp: 20200122T195904Z
Authorization: CTN1-HMAC-SHA256 Credential=d8YpQ7jgPBJEkBrnvp58/20200122/ctn1_request, Signature=867604b6d15575907e6c40ca8ef5f5d07c4791eed1a7a6a0fc358cd5d850948a
Content-Type: application/json; charset=utf-8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.10 (Macintosh; OS X/10.15.2) GCDHTTPRequest
Content-Length: 111

{"message":"This is only a test","options":{"encoding":"utf8","encrypt":true,"offChain":true,"storage":"auto"}}
curl -X "POST" "http://localhost:3000/api/0.11/messages/log" \
     -H 'X-BCoT-Timestamp: 20200122T195936Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=d8YpQ7jgPBJEkBrnvp58/20200122/ctn1_request, Signature=a68ef08c0f45b23a557440cc505380b30c1850828c75b8a96d351d129d3022db' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "message": "This is only a test",
  "options": {
    "encoding": "utf8",
    "encrypt": true,
    "offChain": true,
    "storage": "auto"
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.logMessage('This is only a test', {
        encoding: 'utf8',
        encrypt: true,
        offChain: true,
        storage: 'auto'
    },
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('ID of logged message:', data.messageId);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.logMessage('This is only a test', {
        encoding: 'utf8',
        encrypt: true,
        offChain: true,
        storage: 'auto'
    },
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('ID of logged message:', data.messageId);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->logMessage('This is only a test', [
        'encoding' => 'utf8',
        'encrypt' => true,
        'offChain' => true,
        'storage' => 'auto'
    ]);

    // Process returned data
    echo 'ID of logged message: ' . $data->messageId . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.log_message(
        Message::Whole(String::from("This is only a test")),
        Some(LogMessageOptions {
            encoding: Some(Encoding::UTF8),
            encrypt: Some(true),
            off_chain: Some(true),
            storage: Some(Storage::Auto),
            async_: None,
        }),
    )?;

    println!("ID of logged message: {}", result.message_id.unwrap());

    Ok(())
}

Accessibility

Private

Request

POST /messages/log

Parameters

A JSON containing the following properties:

Property Type Description
message String|Object The message to record. If an object is passed instead, it is expected that the message be passed in chunks.
  data String (optional) The next message data chunk. The actual message's contents should be comprised of one or more data chunks.
  isFinal Boolean (optional, default: true) Indicates whether this is the final message data chunk.
  continuationToken String (optional) Indicates that this is a continuation message data chunk. It should be filled with the value returned in the continuationToken field of the response to the request used to pass the previous message data chunk.
options Object (optional)
  encoding String (optional, default: utf8) Value identifying the encoding of the message. Valid options: utf8, base64, hex.
  encrypt Boolean (optional, default: true) Indicates whether message should be encrypted before storing it.
  offChain Boolean (optional, default: true) Indicates whether message should be logged as a Catenis off-chain message.
  storage String (optional, default: auto) Value identifying where the message should be stored. Valid options: auto, embedded, external. The value embedded specifies that the message should be stored on the blockchain transaction itself; the value external specifies that the message should be stored in an external repository; and the value auto is used to specify that the message be embedded whenever possible otherwise it should be stored in the external storage.
  async Boolean (optional, default: false) Indicates whether processing — storage of message to the blockchain — should be done asynchronously.

Sample response:

{
  "status": "success",
  "data": {
    "messageId": "ouczbRbcgo3F8XoC6ejE"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  continuationToken String (only returned if passing message in chunks and last message data chunk was not final) Token to be used when sending the following message data chunk.
  messageId String (only returned after message has been processed) ID of the logged message.
  provisionalMessageId String (only returned if doing asynchronous processing after the whole message's contents are passed) ID of provisional message.

Possible errors

Status code Error message
400 Invalid or unexpected continuation token
Invalid parameters: <param_list>
Message already complete
Message expired
Message too long to be embedded
Not enough credits to pay for log message service
413 Request data too large to be processed
500 Internal server error
503 System currently not available; please try again at a later time

Migrate Asset

Migrate an amount of a previously exported asset to/from the foreign blockchain token.

The migration can occur in two directions: outward or inward. When out-migrating, the specified amount is deducted from the asset and credited to the foreign token. Otherwise, when in-migrating, the specified amount is deducted from the foreign token and credited to the asset.

Sample request:

POST /api/0.11/assets/aH2AkrrL55GcThhPNa3J/migrate/ethereum HTTP/1.1
X-BCoT-Timestamp: 20210810T121125Z
Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210810/ctn1_request, Signature=e0493fed7f758c444bc29be683723165e255df40549ecc60d292d5745e1dcb68
Content-Type: application/json; charset=utf-8
Host: localhost:3000
Connection: close
User-Agent: Paw/3.2.3 (Macintosh; OS X/11.5.0) GCDHTTPRequest
Content-Length: 108

{"migration":{"direction":"outward","amount":50.5,"destAddress":"0xe247c9BfDb17e7D8Ae60a744843ffAd19C784943"}}
curl -X "POST" "http://localhost:3000/api/0.11/assets/aH2AkrrL55GcThhPNa3J/migrate/ethereum" \
     -H 'X-BCoT-Timestamp: 20210809T203625Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=drc3XdxNtzoucpw9xiRp/20210809/ctn1_request, Signature=a94d8ed1df52dfd21959f3a04436bdc68f47ea41685cd7f20fbf126f6fec63df' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "migration": {
    "amount": 50.5,
    "direction": "outward",
    "destAddress": "0xe247c9BfDb17e7D8Ae60a744843ffAd19C784943"
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aH2AkrrL55GcThhPNa3J';
var foreignBlockchain = 'ethereum';

ctnApiClient.migrateAsset(assetId, foreignBlockchain, {
    direction: 'outward',
    amount: 50.5,
    destAddress: '0xe247c9BfDb17e7D8Ae60a744843ffAd19C784943'
}, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Pending asset migration:', data);

        // Start polling for asset migration outcome
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aH2AkrrL55GcThhPNa3J';
var foreignBlockchain = 'ethereum';

ctnApiClient.migrateAsset(assetId, foreignBlockchain, {
    direction: 'outward',
    amount: 50.5,
    destAddress: '0xe247c9BfDb17e7D8Ae60a744843ffAd19C784943'
}, function (error, data) {
    if (error) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Pending asset migration:', data);

        // Start polling for asset migration outcome
    }
});
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aH2AkrrL55GcThhPNa3J';
$foreignBlockchain = 'ethereum';

try {
    $data = $ctnApiClient->migrateAsset($assetId, $foreignBlockchain, [
        'direction' => 'outward',
        'amount' => 50.5,
        'destAddress' => '0xe247c9BfDb17e7D8Ae60a744843ffAd19C784943'
    ]);

    // Process returned data
    echo 'Pending asset migration: ' . print_r($data, true);

    // Start polling for asset migration outcome
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aH2AkrrL55GcThhPNa3J";

    let result = ctn_client.migrate_asset(
        asset_id,
        ForeignBlockchain::Ethereum,
        AssetMigration::Info(AssetMigrationInfo {
            direction: AssetMigrationDirection::Outward,
            amount: 50.5,
            dest_address: Some(String::from("0xe247c9BfDb17e7D8Ae60a744843ffAd19C784943")),
        }),
        None,
    )?;

    println!("Pending asset migration: {:?}", result);

    // Start polling for asset migration outcome

    Ok(())
}

Accessibility

Private

Request

POST /assets/:assetId/migrate/:foreignBlockchain

Parameters

A JSON containing the following properties:

Property Type Description
migration Object|String Object describing a new asset migration, or the ID of the asset migration to be reprocessed.
  direction String The direction of the migration. Valid options: outward, inward.
  amount Number The amount of the asset to be migrated.
  destAddress String (optional, only required for an out-migration) The address of the account on the foreign blockchain that should be credited with the specified amount of the foreign token.
options Object (optional)
  consumptionProfile String (optional) Name of the foreign blockchain's native coin consumption profile to use. Valid options: fastest, fast, average, slow.
  estimateOnly Boolean (optional, default: false) When set, indicates that no asset migration should be executed but only the estimated price (in the foreign blockchain's native coin) to fulfill the operation should be returned.

Sample response (regular migration):

{
  "status": "success",
  "data": {
    "migrationId": "gq8x3efLpEXTkGQchHTb",
    "catenisService": {
      "status": "fulfilled",
      "txid": "61fcb4feb64ecf3b39b4bb6d64eb9cc68a58ba1d892f981ef568d07b7aa11fdf"
    },
    "foreignTransaction": {
      "txid": "0x212ab54f136a6fc1deae9ec217ef2d0417615178777131e8bb6958447fd20fe7",
      "isPending": true
    },
    "status": "pending",
    "date": "2021-08-03T18:51:26.631Z"
  }
}

Sample response (estimate only):

{
  "status": "success",
  "data": {
    "estimatedPrice": "0.001723913"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  migrationId String (not returned for estimate only) A unique ID used to identify this asset migration.
  catenisService Object (not returned for estimate only) Information about the execution of the migrate asset Catenis service.
    status String The current state of the service's execution. One of: awaiting, failure, or fulfilled.
    txid String (only returned if the service is successfully fulfilled) The ID of the Catenis transaction issued to fulfill the service.
    error String (only returned if the service's execution has failed) An error message describing what went wrong when executing the service.
  foreignTransaction Object (not returned for estimate only) Information about the transaction issued on the foreign blockchain to mint/burn the amount of the foreign token.
    txid String The ID (or hash) of the foreign blockchain transaction.
    isPending Boolean Indicates whether the foreign blockchain transaction is yet to be executed.
    success Boolean (only returned after the foreign blockchain transaction is executed) Indicates whether the foreign blockchain transaction has been successfully executed or not.
    error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
  status String (not returned for estimate only) The current state of the asset migration. One of: pending, interrupted, success, or error.
  date String (not returned for estimate only) ISO 8601 formatted date and time when the asset amount has been migrated.
  estimatedPrice String (only returned for estimate only) A text value representing the price, in the foreign blockchain's native coin, required to execute the foreign blockchain transaction.

Possible errors

Status code Error message
400 Amount to migrate is too large
Asset is not yet exported
Asset migration already successfully processed
Discarded concurrent foreign token smart contract call
Foreign blockchain funds not enough to cover transaction execution price (<value>)
Foreign token balance too low to in-migrate the asset amount
Insufficient balance to out-migrate asset
Insufficient migrated asset amount to in-migrate asset
Invalid asset ID
Invalid asset migration ID
Invalid foreign blockchain destination address
Invalid parameters: <param_list>
Mismatched asset migration
Not enough credits to pay for migrate asset service
Unexpected error calling foreign token smart contract
403 No permission to migrate asset
500 Internal server error
503 System currently not available; please try again at a later time

Read Message

Retrieves the contents of a message that had been previously recorded on the blockchain.

Sample request:

GET /api/0.11/messages/oDWPuD5kjCsEiNEEWwrW?encoding=utf8 HTTP/1.1
X-BCoT-Timestamp: 20180215T112048Z
Authorization: CTN1-HMAC-SHA256 Credential=dmM2Dz32agLSGsSuoxsR/20180215/ctn1_request, Signature=10b1299fdf935544b44e3e1e8de7d3f3df03df9ddc35db0127d5ab0cafa36cbb
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/messages/oDWPuD5kjCsEiNEEWwrW?encoding=utf8" \
     -H 'X-BCoT-Timestamp: 20180215T112120Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dmM2Dz32agLSGsSuoxsR/20180215/ctn1_request, Signature=84ddc0f0e3a3cadab6011b18962912bdf62bfcd2234e0984513a1856fd88c1c1'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var messageId = 'oDWPuD5kjCsEiNEEWwrW';

ctnApiClient.readMessage(messageId, 'utf8', function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Read message:', data.msgData.message);

        if (data.msgInfo.action === 'send') {
            console.log('Message sent from:', data.msgInfo.from);
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var messageId = 'oDWPuD5kjCsEiNEEWwrW';

ctnApiClient.readMessage(messageId, 'utf8', function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Read message:', data.message);

        if (data.action === 'send') {
            console.log('Message sent from:', data.from);
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$messageId = 'oDWPuD5kjCsEiNEEWwrW';

try {
    $data = $ctnApiClient->readMessage($messageId, 'utf8');

    // Process returned data
    echo 'Read message: ' . $data->message . PHP_EOL;

    if ($data->action === 'send') {
        echo 'Message sent from: ' . print_r($data->from, true);
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let message_id = "oDWPuD5kjCsEiNEEWwrW";

    let result = ctn_client.read_message(
        message_id,
        Some(ReadMessageOptions {
            encoding: Some(Encoding::UTF8),
            continuation_token: None,
            data_chunk_size: None,
            async_: None,
        }),
    )?;

    println!("Read message: {}", result.msg_data.unwrap());

    let msg_info = result.msg_info.unwrap();

    if msg_info.action == RecordMessageAction::Send {
        println!("Message sent from: {:?}", msg_info.from.unwrap());
    }

    Ok(())
}

Accessibility

Private

Request

GET /messages/:messageId

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "msgInfo": {
      "action": "send",
      "from": {
        "deviceId": "dv3htgvK7hjnKx3617Re",
        "name": "Catenis device #1"
      }
    },
    "msgData": "This is only a test"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  msgInfo Object (only returned along with the msgData field if not reading the message in chunks or for the first message data chunk returned) Info about the read message.
    action String Action originally performed on the message. Possible values: log, send. The value log indicates that this is a logged message, and the value send indicates that this is a sent message.
    from Object (only returned for sent messages) Identifies the virtual device that sent the message — the origin device.
      deviceId String The device ID of the origin device.
      name String (only returned if origin device has this data, and the virtual device issuing the request has the necessary permission right) The name of the origin device.
      prodUniqueId String (only returned if origin device has this data, and the virtual device issuing the request has the necessary permission right) The product unique ID of the origin device.
  msgData String (always returned except when cachedMessageId field is returned) The contents of the message formatted using the specified encoding. When reading the message in chunks, this corresponds to a message data chunk. In that case, additional calls to this API method might be necessary to read the whole message's contents.
  continuationToken String (only returned along with the msgData field if the whole message's contents have not yet been returned) Token to be used when requesting the following message data chunk.
  cachedMessageId String (only returned as a response to the initial call to this API method to read a given message asynchronously — async parameter set to true) Cached message ID.

Possible errors

Status code Error message
400 Invalid message ID
Invalid or unexpected continuation token
Invalid parameters: <param_list>
Message already read
Message expired
Message not available
Message too large for reading at once
403 No permission to read message
500 Internal server error
503 System currently not available; please try again at a later time

Reissue Asset

Issues an additional amount of an existing asset.

Sample request:

POST /api/0.11/assets/aQjlzShmrnEZeeYBZihc/issue/ HTTP/1.1
X-BCoT-Timestamp: 20180417T004201Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=71d61d674882e0bcfadcda962cf3393b300af6f0cbbc5fb211f1f33d5bbd8b3a
Content-Type: application/json; charset=utf-8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
Content-Length: 60

{"amount":450,"holdingDevice":{"id":"dv3htgvK7hjnKx3617Re"}}
curl -X "POST" "https://sandbox.catenis.io/api/0.11/assets/aQjlzShmrnEZeeYBZihc/issue/" \
     -H 'X-BCoT-Timestamp: 20180417T004241Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=bfed2a3062c5ee48623ff863d5bc5bedee85189303617be7b01b080c8d9ca950' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "amount": 450,
  "holdingDevice": {
    "id": "dv3htgvK7hjnKx3617Re"
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';
var holdingDevice = {
    id: 'dv3htgvK7hjnKx3617Re'
};

ctnApiClient.reissueAsset(assetId, 450.00, holdingDevice,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Total existent asset balance (after issuance):', data.totalExistentBalance);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';
var holdingDevice = {
    id: 'dv3htgvK7hjnKx3617Re'
};

ctnApiClient.reissueAsset(assetId, 450.00, holdingDevice,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Total existent asset balance (after issuance):', data.totalExistentBalance);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aQjlzShmrnEZeeYBZihc';
$holdingDevice = [
   'id' => 'dv3htgvK7hjnKx3617Re'
];

try {
    $data = $ctnApiClient->reissueAsset($assetId, 450.00, $holdingDevice);

    // Process returned data
    echo 'Total existent asset balance (after issuance): ' . $data->totalExistentBalance . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aQjlzShmrnEZeeYBZihc";
    let holding_device = DeviceId {
        id: String::from("dv3htgvK7hjnKx3617Re"),
        is_prod_unique_id: None,
    };

    let result = ctn_client.reissue_asset(
        asset_id,
        650.25,
        Some(holding_device),
    )?;

    println!("Total existent asset balance (after issuance): {}", result.total_existent_balance);

    Ok(())
}

Accessibility

Private

Request

POST /assets/:assetId/issue

Parameters

A JSON containing the following properties:

Property Type Description
amount Number The amount of asset to issue.
holdingDevice Object (optional) Virtual device for which the asset is issued and that shall hold the issued amount.
  id String The ID of the holding device. Should be a device ID unless isProdUniqueId is set.
  isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.

Sample response:

{
  "status": "success",
  "data": {
    "totalExistentBalance": 1650
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  totalExistentBalance Number Total balance of the asset in existence after specified amount has been issued.

Possible errors

Status code Error message
400 Amount to issue is too large
Asset cannot be reissued
Invalid asset ID
Invalid holding device
Invalid parameters: <param_list>
Not enough credits to pay for issue asset service
403 No permission to reissue asset
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Asset Info

Gets information about a given asset.

Sample request:

GET /api/0.11/assets/aQjlzShmrnEZeeYBZihc HTTP/1.1
X-BCoT-Timestamp: 20180417T143840Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=d73532614d4e46fb4e9be59255a660b540a122322aa7800fcb8a0ea4c3a0e40a
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/assets/aQjlzShmrnEZeeYBZihc" \
     -H 'X-BCoT-Timestamp: 20180417T143900Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=b6501dab96c6838807817c63d9e75f5020806c5a4a0075558a7ff3477b468a1a'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.retrieveAssetInfo(assetId,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Asset info:', data);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.retrieveAssetInfo(assetId,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Asset info:', data);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aQjlzShmrnEZeeYBZihc';

try {
    $data = $ctnApiClient->retrieveAssetInfo($assetId);

    // Process returned data
    echo 'Asset info:' . print_r($data, true);
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aQjlzShmrnEZeeYBZihc";

    let result = ctn_client.retrieve_asset_info(
        asset_id,
    )?;

    println!("Asset info: {:?}", result);

    Ok(())
}

Accessibility

Private

Request

GET /assets/:assetId

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "assetId": "aQjlzShmrnEZeeYBZihc",
    "name": "XYZ001",
    "description": "Testing asset #1",
    "canReissue": true,
    "decimalPlaces": 2,
    "issuer": {
      "deviceId": "dnN3Ea43bhMTHtTvpytS",
      "name": "deviceB",
      "prodUniqueId": "XYZABC001"
    },
    "totalExistentBalance": 1650
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  assetId String The ID of the asset.
  name String The name of the asset.
  description String The description of the asset.
  canReissue Boolean Indicates whether more units of this asset can be issued.
  decimalPlaces Number The maximum number of decimal places that can be used to specify a fractional amount of this asset.
  issuer Object The virtual device that originally issued this asset — the issuing device.
    deviceId String The device ID of the issuing device.
    name String (only returned if issuing device has this data, and the virtual device issuing the request has the necessary permission right) The name of the issuing device.
    prodUniqueId String (only returned if issuing device has this data, and the virtual device issuing the request has the necessary permission right) The product unique ID of the issuing device.
  totalExistentBalance Number The current total balance of the asset in existence.

Possible errors

Status code Error message
400 Invalid asset ID
Invalid parameters: <param_list>
403 No permission to retrieve asset info
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Asset Issuance History

Gets a list of asset issuance events for a given asset that took place within a specified time frame.

Sample request:

GET /api/0.11/assets/aQjlzShmrnEZeeYBZihc/issuance?startDate=20170101T000000Z&limit=200&skip=0 HTTP/1.1
X-BCoT-Timestamp: 20180417T182853Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=57d779fbb24593ba4eff574e0c87961a3c39561cb90d99546d5041cdd7e964a9
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/assets/aQjlzShmrnEZeeYBZihc/issuance?startDate=20170101T000000Z&limit=200&skip=0" \
     -H 'X-BCoT-Timestamp: 20180417T182836Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=4990e4df2d0d73d01cd251dab65b6f4d2f702b43eb517d88c5ff3038d0bbd1f6'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.retrieveAssetIssuanceHistory(assetId, '20170101T000000Z', null, 200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.issuanceEvents.forEach(function (issuanceEvent, idx) {
                console.log('Issuance event #', idx + 1, ':');
                console.log('  - issued amount:', issuanceEvent.amount);
                console.log('  - device to which issued amount had been assigned:', issuanceEvent.holdingDevice);
                console.log('  - date of issuance:', issuanceEvent.date);
            });

            if (data.hasMore) {
                console.log('Not all asset issuance events have been returned');
            }
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';

ctnApiClient.retrieveAssetIssuanceHistory(assetId, '20170101T000000Z', null, 200, 0,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            data.issuanceEvents.forEach(function (issuanceEvent, idx) {
                console.log('Issuance event #', idx + 1, ':');
                console.log('  - issued amount:', issuanceEvent.amount);
                console.log('  - device to which issued amount had been assigned:', issuanceEvent.holdingDevice);
                console.log('  - date of issuance:', issuanceEvent.date);
            });

            if (data.hasMore) {
                console.log('Not all asset issuance events have been returned');
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aQjlzShmrnEZeeYBZihc';

try {
    $data = $ctnApiClient->retrieveAssetIssuanceHistory($assetId, '20170101T000000Z', null, 200, 0);

    // Process returned data
    forEach($data->issuanceEvents as $idx => $issuanceEvent) {
        echo 'Issuance event #', ($idx + 1) . ':' . PHP_EOL;
        echo '  - issued amount: ' . $issuanceEvent->amount . PHP_EOL;
        echo '  - device to which issued amount had been assigned: ' . print_r($issuanceEvent->holdingDevice, true);
        echo '  - date of issuance: ' . $issuanceEvent->date . PHP_EOL;
    }

    if ($data->hasMore) {
        echo 'Not all asset issuance events have been returned' . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aQjlzShmrnEZeeYBZihc";

    let result = ctn_client.retrieve_asset_issuance_history(
        asset_id,
        Some("2017-01-01T00:00:00Z".into()),
        None,
        Some(200),
        Some(0),
    )?;

    for idx in 0..result.issuance_events.len() {
        let issuance_event = &result.issuance_events[idx];

        println!("Issuance event #{}:", idx + 1);
        println!(" - asset amount: {}", issuance_event.amount);
        println!(" - device to which issued amount had been assigned: {:?}", issuance_event.holding_device);
        println!(" - date of issuance: {}", issuance_event.date);
    }

    if result.has_more {
        println!("Not all asset issuance events have been returned");
    }

    Ok(())
}

Accessibility

Private

Request

GET /assets/:assetId/issuance

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "issuanceEvents": [
      {
        "amount": 1200,
        "holdingDevice": {
          "deviceId": "dnN3Ea43bhMTHtTvpytS",
          "name": "deviceB",
          "prodUniqueId": "XYZABC001"
        },
        "date": "2018-03-27T21:43:15.050Z"
      },
      {
        "amount": 450,
        "holdingDevice": {
          "deviceId": "dv3htgvK7hjnKx3617Re",
          "name": "Catenis device #1"
        },
        "date": "2018-03-28T12:20:31.738Z"
      }
    ],
    "hasMore": false
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  issuanceEvents Array(Object) The list of asset issuance events returned. The events are sorted in ascending order in regard to the returned date field.
    amount Number The amount of the asset issued.
    holdingDevice Object The virtual device to which the issued amount was assigned.
      deviceId String The device ID of the holding device.
      name String (only returned if holding device has this data, and the virtual device issuing the request has the necessary permission right) The name of the holding device.
      prodUniqueId String (only returned if holding device has this data, and the virtual device issuing the request has the necessary permission right) The product unique ID of the holding device.
    date String ISO 8601 formatted date and time when the asset has been issued.
  hasMore Boolean Indicates whether there are more asset issuance events that satisfy the search criteria yet to be returned.

Possible errors

Status code Error message
400 Invalid asset ID
Invalid parameters: <param_list>
403 No permission to retrieve asset issuance history
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Device Identification Info

Gets the identification information of a given virtual device.

Sample request:

GET /api/0.11/devices/dv3htgvK7hjnKx3617Re HTTP/1.1
X-BCoT-Timestamp: 20180219T133757Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180219/ctn1_request, Signature=ff2a8f3d8dc232d60208dc28f668351234ed25ead274e820ac081a480a275012
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/devices/dv3htgvK7hjnKx3617Re" \
     -H 'X-BCoT-Timestamp: 20180219T133846Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180219/ctn1_request, Signature=74b0618fe8fe40278b3325cccdac350bed538a5faac86689c3d07e3f1df085f0'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var checkDeviceId = 'dv3htgvK7hjnKx3617Re';

ctnApiClient.retrieveDeviceIdentificationInfo(checkDeviceId, false, function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Device\'s Catenis node ID info:', data.catenisNode);
        console.log('Device\'s client ID info:', data.client);
        console.log('Device\'s own ID info:', data.device);
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var checkDeviceId = 'dv3htgvK7hjnKx3617Re';

ctnApiClient.retrieveDeviceIdentificationInfo(checkDeviceId, false, function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Device\'s Catenis node ID info:', data.catenisNode);
        console.log('Device\'s client ID info:', data.client);
        console.log('Device\'s own ID info:', data.device);
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$checkDeviceId = 'dv3htgvK7hjnKx3617Re';

try {
    $data = $ctnApiClient->retrieveDeviceIdentificationInfo($checkDeviceId);

    // Process returned data
    echo 'Device\'s Catenis node ID info:' . print_r($data->catenisNode, true);
    echo 'Device\'s client ID info:' . print_r($data->client, true);
    echo 'Device\'s own ID info:' . print_r($data->device, true);
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let check_device = DeviceId {
        id: String::from("dv3htgvK7hjnKx3617Re"),
        is_prod_unique_id: None,
    };

    let result = ctn_client.retrieve_device_identification_info(
        check_device,
    )?;

    println!("Device's Catenis node ID info: {:?}", result.catenis_node);
    println!("Device's client ID info: {:?}", result.client);
    println!("Device's own ID info: {:?}", result.device);

    Ok(())
}

Accessibility

Private

Request

GET /devices/:deviceId

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "catenisNode": {
      "ctnNodeIndex": 0,
      "name": "Catenis Hub",
      "description": "Central Catenis node used to house clients that access the system through the Internet"
    },
    "client": {
      "clientId": "cjNhuvGMUYoepFcRZadP",
      "name": "My test client"
    },
    "device": {
      "deviceId": "dv3htgvK7hjnKx3617Re",
      "name": "Catenis device #1"
    }
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  catenisNode Object Information about the Catenis node where the client to which the specified virtual device belongs is defined.
    ctnNodeIndex Number The index of the Catenis node.
    name String (only returned if Catenis node has this data) The name of the Catenis node.
    description String (only returned if Catenis node has this data) A short description about the Catenis node.
  client Object Information about the client to which the specified virtual device belongs.
    clientId String The client ID of the client.
    name String (only returned if client has this data) The name of the client.
  device Object Information about the specified virtual device itself.
    deviceId String The device ID of the virtual device.
    name String (only returned if virtual device has this data) The name of the virtual device.
    prodUniqueId String (only returned if virtual device has this data) The product unique ID of the virtual device.

Possible errors

Status code Error message
400 Invalid device
Invalid parameters: <param_list>
403 No permission to retrieve info
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Message Container

Gets information about the place where a previously recorded — either logged or sent — message is actually stored.

Sample request:

GET /api/0.11/messages/oDWPuD5kjCsEiNEEWwrW/container HTTP/1.1
X-BCoT-Timestamp: 20180215T200325Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180215/ctn1_request, Signature=f06dc359270c2a3a91326ef2e7fd5506fd75dc9740b2609ed796ce01b3f92afb
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/messages/oDWPuD5kjCsEiNEEWwrW/container" \
     -H 'X-BCoT-Timestamp: 20180215T200350Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180215/ctn1_request, Signature=7e50993e18975294f7f22aae7ee7ef4e4d68425502e38961c40743b1f72194eb'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var messageId = 'oDWPuD5kjCsEiNEEWwrW';

ctnApiClient.retrieveMessageContainer(messageId, function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        if (data.offChain) {
            console.log('IPFS CID of Catenis off-chain message envelope:', data.offChain.cid);
        }

        if (data.blockchain) {
            console.log('ID of blockchain transaction containing the message:', data.blockchain.txid);
        }

        if (data.externalStorage) {
            console.log('IPFS reference to message:', data.externalStorage.ipfs);
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var messageId = 'oDWPuD5kjCsEiNEEWwrW';

ctnApiClient.retrieveMessageContainer(messageId, function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        if (data.offChain) {
            console.log('IPFS CID of Catenis off-chain message envelope:', data.offChain.cid);
        }

        if (data.blockchain) {
            console.log('ID of blockchain transaction containing the message:', data.blockchain.txid);
        }

        if (data.externalStorage) {
            console.log('IPFS reference to message:', data.externalStorage.ipfs);
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$messageId = 'oDWPuD5kjCsEiNEEWwrW';

try {
    $data = $ctnApiClient->retrieveMessageContainer($messageId);

    // Process returned data
    if (isset($data->offChain)) {
        echo 'IPFS CID of Catenis off-chain message envelope: ' . $data->offChain->cid . PHP_EOL;
    }

    if (isset($data->blockchain)) {
        echo 'ID of blockchain transaction containing the message: ' . $data->blockchain->txid . PHP_EOL;
    }

    if (isset($data->externalStorage)) {
        echo 'IPFS reference to message: ' . $data->externalStorage->ipfs . PHP_EOL;
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let message_id = "oDWPuD5kjCsEiNEEWwrW";

    let result = ctn_client.retrieve_message_container(
        message_id,
    )?;

    if let Some(off_chain) = result.off_chain {
        println!("IPFS CID of Catenis off-chain message envelope: {}", off_chain.cid);
    }

    if let Some(blockchain) = result.blockchain {
        println!("ID of blockchain transaction containing the message: {}", blockchain.txid);
    }

    if let Some(external_storage) = result.external_storage {
        println!("IPFS reference to message: {}", external_storage.ipfs);
    }

    Ok(())
}

Accessibility

Private

Request

GET /messages/:messageId/container

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "offChain": {
      "cid": "QmUPNgbkB2esFHLZdS5rhD8wxFaCBU8JeBrBePWqMfSWub"
    },
    "blockchain": {
      "txid": "e4080d2badac0b4d4524aa20cd3abfa2f1bdd05a15c85b9d156374c7c6bbfc82",
      "isConfirmed": true
    },
    "externalStorage": {
      "ipfs": "QmQ2UaYLHwSjU4VvHyD4SfCUyo7AvrufdNrX1kmsbtbn3w"
    }
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  offChain Object (only returned for Catenis off-chain messages)
    cid String IPFS CID of Catenis off-chain message envelope data structure that holds the off-chain message's contents.
  blockchain Object (for Catenis off-chain messages, this property refers to the transaction used to settle the message to the blockchain, and it is only returned at a later time after the settlement takes place)
    txid String The ID of the blockchain transaction where the message was recorded.
    isConfirmed Boolean Indicates whether the blockchain transaction has already been confirmed.
  externalStorage Object (only returned if message is stored on an external storage rather than on the blockchain transaction itself)
    ipfs String The hash used to reference the message on IPFS.

Possible errors

Status code Error message
400 Invalid message ID
Invalid parameters: <param_list>
403 No permission to retrieve message container
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Message Origin *

Gets information about the origin of a previously recorded — either logged or sent — message.

Sample request:

GET /api/0.11/messages/oDWPuD5kjCsEiNEEWwrW/origin?msgToSign=This%20is%20only%20a%20test HTTP/1.1
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/messages/oDWPuD5kjCsEiNEEWwrW/origin?msgToSign=This%20is%20only%20a%20test"
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var ctnApiClient = new CtnApiClient({
    environment: 'sandbox'
});

var messageId = 'oDWPuD5kjCsEiNEEWwrW';

ctnApiClient.retrieveMessageOrigin(messageId, 'Any text to be signed',
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            if (data.tx) {
                console.log('Catenis message transaction info:', data.tx);
            }

            if (data.offChainMsgEnvelope) {
                console.log('Off-chain message envelope info:', data.offChainMsgEnvelope);
            }

            if (data.proof) {
                console.log('Origin proof info:', data.proof);
            }
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var ctnApiClient = new CtnApiClient({
    environment: 'sandbox'
});

var messageId = 'oDWPuD5kjCsEiNEEWwrW';

ctnApiClient.retrieveMessageOrigin(messageId, 'Any text to be signed',
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            if (data.tx) {
                console.log('Catenis message transaction info:', data.tx);
            }

            if (data.offChainMsgEnvelope) {
                console.log('Off-chain message envelope info:', data.offChainMsgEnvelope);
            }

            if (data.proof) {
                console.log('Origin proof info:', data.proof);
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$ctnApiClient = new ApiClient(null, null, [
    'environment' => 'sandbox'
]);

$messageId = 'oDWPuD5kjCsEiNEEWwrW';

try {
    $data = $ctnApiClient->retrieveMessageOrigin($messageId, 'Any text to be signed');

    // Process returned data
    if (isset($data->tx)) {
        echo 'Catenis message transaction info: ' . print_r($data->tx, true);
    }

    if (isset($data->offChainMsgEnvelope)) {
        echo 'Off-chain message envelope info: ' . print_r($data->offChainMsgEnvelope, true);
    }

    if (isset($data->proof)) {
        echo 'Origin proof info: ' . print_r($data->proof, true);
    }
}
catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let ctn_client = CatenisClient::new_with_options(
        None,
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let message_id = "oDWPuD5kjCsEiNEEWwrW";

    let result = ctn_client.retrieve_message_origin(
        message_id,
        Some("Any text to be signed"),
    )?;

    if let Some(tx) = result.tx {
        println!("Catenis message transaction info: {:?}", tx);
    }

    if let Some(off_chain_msg_env) = result.off_chain_msg_envelope {
        println!("Off-chain message envelope info: {:?}", off_chain_msg_env);
    }

    if let Some(proof) = result.proof {
        println!("Origin proof info: {:?}", proof);
    }

    Ok(())
}

Accessibility

Public

Request

GET /messages/:messageId/origin

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "tx": {
      "txid": "e80b97c1ee45da349f774e4e509c0ddce56003fa737ef37ab22e1b676fe4a9c8",
      "type": "Settle Off-Chain Messages",
      "batchDoc": {
        "cid": "QmT2kJRaShQbMEzjDVmqMtsjccqvUaemNNrXzkv6oVgi6d"
      }
    },
    "offChainMsgEnvelope": {
      "cid": "Qmd7xeEwwmWrJpovmTYhCTRjpfRPr9mtDxj7VRscrcqsgP",
      "type": "Log Message",
      "originDevice": {
        "pubKeyHash": "25f154093fe70c4a45518f858a1edececf208ee6",
        "deviceId": "drc3XdxNtzoucpw9xiRp",
        "name": "TstDev1",
        "prodUniqueId": "ABC123",
        "ownedBy": {
          "company": "Blockchain of Things",
          "contact": "Cláudio de Castro",
          "domains": [
            "blockchainofthings.com",
            "catenis.io"
          ]
        }
      }
    },
    "proof": {
      "message": "This is only a test",
      "signature": "H6bt6sl7T6VpOUQ1of0rjYEmT3u14h8gP7kmoWG4aEblNNc9Zx00tRaxcxPZgSxkmWH2427FBOFE5W/t9fgW4eU="
    }
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  tx Object (not returned for off-chain messages not yet settled to the blockchain) Information about the blockchain transaction used to record the Catenis message to the blockchain — the Catenis message transaction.
    txid String ID of Catenis message transaction.
    type String Type of Catenis message transaction. One of: Send Message, Log Message, or Settle Off-Chain Messages.
    batchDoc Object (only returned for off-chain messages) Information about the batch document used to settle off-chain messages on the blockchain.
      cid String Content ID (CID) of batch document on IPFS.
    originDevice Object (not returned for off-chain messages) Information about the virtual device that recorded the message — the origin device.
      address String Origin device's blockchain address used to generate the Catenis message transaction.
      deviceId String Device ID of origin device.
      name String (only returned if defined) Origin device's name.
      prodUniqueId String (only returned if defined) Origin device's product unique ID.
      ownedBy Object
        company String (only returned if defined) Name of company that owns the origin device.
        contact String (only returned if defined and company is returned) Name of company's contact.
        name String (only returned if company is not returned) Name of the person who owns the origin device.
        domains Array(String) (only returned if defined) List of internet domains owned by this company or person.
  offChainMsgEnvelope Object (only returned for off-chain messages) Information about the off-chain message envelope data structure used to record the Catenis message on IPFS.
    cid String Content ID (CID) of off-chain message envelope on IPFS.
    type String Type of Catenis off-chain message. One of: Send Message, or Log Message.
    originDevice Object (not returned for off-chain messages) Information about the virtual device that recorded the message — the origin device.
      pubKeyHash String Hex-encoded hash of origin device's public key used to generate the off-chain message envelope.
      deviceId String Device ID of origin device.
      name String (only returned if defined) Origin device's name.
      prodUniqueId String (only returned if defined) Origin device's product unique ID.
      ownedBy Object
        company String (only returned if defined) Name of company that owns the origin device.
        contact String (only returned if defined and company is returned) Name of company's contact.
        name String (only returned if company is not returned) Name of the person who owns the origin device.
        domains Array(String) (only returned if defined) List of internet domains owned by this company or person.
  proof Object (only returned if msgToSign parameter is supplied)
    message String Message for which the signature was generated.
    signature String Base64-encoded message's signature generated using origin device's private key.

Possible errors

Status code Error message
400 Invalid message ID
403 Message origin cannot be disclosed
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Message Progress

Retrieves the current status of the asynchronous processing of a message.

Sample request:

GET /api/0.11/messages/hfHtyPCS68toB9FjA8rM/progress HTTP/1.1
X-BCoT-Timestamp: 20190318T212628Z
Authorization: CTN1-HMAC-SHA256 Credential=dL8zaQDcyNvxRW3FqsJd/20190318/ctn1_request, Signature=d98b79672098eeea5f261e102d213168f757c3234a3ee28a2192b5acd739e664
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.8 (Macintosh; OS X/10.14.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/messages/hfHtyPCS68toB9FjA8rM/progress" \
     -H 'X-BCoT-Timestamp: 20190318T212739Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dL8zaQDcyNvxRW3FqsJd/20190318/ctn1_request, Signature=3ee6e3c7fe58319e4b53a7342a38af2a923908bbe1da5864f5f800d7330abdc1'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var cachedMessageId = 'hfHtyPCS68toB9FjA8rM';

ctnApiClient.retrieveMessageProgress(cachedMessageId,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Number of bytes processed so far:', data.progress.bytesProcessed);

            if (data.progress.done) {
                if (data.progress.success) {
                    // Get result
                    console.log('Asynchronous processing result:', data.result);
                }
                else {
                    // Process error
                    console.error('Asynchronous processing error: [', data.progress.error.code, ' ] -', data.progress.error.message);
                }
            }
            else {
                // Asynchronous processing not done yet. Continue pooling
            }
        }
});</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var cachedMessageId = 'hfHtyPCS68toB9FjA8rM';

ctnApiClient.retrieveMessageProgress(cachedMessageId,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Number of bytes processed so far:', data.progress.bytesProcessed);

            if (data.progress.done) {
                if (data.progress.success) {
                    // Get result
                    console.log('Asynchronous processing result:', data.result);
                }
                else {
                    // Process error
                    console.error('Asynchronous processing error: [', data.progress.error.code, ' ] -', data.progress.error.message);
                }
            }
            else {
                // Asynchronous processing not done yet. Continue pooling
            }
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$cachedMessageId = 'hfHtyPCS68toB9FjA8rM';

try {
    $data = $ctnApiClient->retrieveMessageProgress($cachedMessageId);

    // Process returned data
    echo 'Number of bytes processed so far: ' . $data->progress->bytesProcessed . PHP_EOL;

    if ($data->progress->done) {
        if ($data->progress->success) {
            // Get result
            echo 'Asynchronous processing result: ' . $data->result . PHP_EOL;
        }
        else {
            // Process error
            echo 'Asynchronous processing error: [' . $data->progress->error->code . '] - '
                . $data->progress->error->message . PHP_EOL;
        }
    } else {
        // Asynchronous processing not done yet. Continue pooling
    }
} catch (\Catenis\Exception\CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let cached_message_id = "hfHtyPCS68toB9FjA8rM";

    let result = ctn_client.retrieve_message_progress(
        cached_message_id,
    )?;

    println!("Number of bytes processed so far: {}", result.progress.bytes_processed);

    if result.progress.done {
        if let Some(true) = result.progress.success {
            // Get result
            println!("Asynchronous processing result: {:?}", result.result.unwrap());
        } else {
            // Process error
            let error = result.progress.error.unwrap();

            println!("Asynchronous processing error: [{}] - {}", error.code, error.message);
        }
    } else {
        // Asynchronous processing not done yet. Continue pooling
    }

    Ok(())
}

Accessibility

Private

Request

GET /messages/:messageId/progress

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "action": "read",
    "progress": {
      "bytesProcessed": 28,
      "done": true,
      "success": true,
      "finishDate": "2019-03-13T14:09:10.121Z"
    },
    "result": {
      "messageId": "mt7ZYbBYpM3zcgAf3H8X",
      "continuationToken": "kjXP2CZaSdkTKCi2jDi2"
    }
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  action String The action that was to be performed on the message. One of: log, send, or read.
  progress Object Current processing status.
    bytesProcessed Number Total number of bytes of message that had already been processed.
    done Boolean Indicates whether processing has been finished.
    success Boolean (only returned if processing has already been finished) Indicates whether message has been successfully processed.
    error Object (only returned if processing finished with error) Error information.
      code Number Numeric code — equivalent to an HTML status code — of the error that took place while processing the message.
      message String Text describing the error that took place while processing the message.
    finishDate String (only returned if processing has already been finished) ISO 8601 formatted date and time when processing was finalized.
  result Object (only returned if processing finished successfully) Result of processing.
    messageId String ID of the Catenis message. When logging or sending — action equals to log or send—, it is the ID of the resulting message. When reading — action equals to read—, it references the message being read.
    continuationToken String (only returned if reading message — action equals to read) The token that should be used to complete the read of the message.

Possible errors

Status code Error message
400 Invalid or expired ephemeral message
Progress not available
500 Internal server error
503 System currently not available; please try again at a later time

Retrieve Permission Rights

Gets the permission rights currently set for a specific permission event.

The virtual device issuing the request acts as the controlling device. Thus the permission rights to be retrieved are the ones set for the pair composed of the permission event specified in the API request and the virtual device issuing the request.

Sample request:

GET /api/0.11/permission/events/receive-msg/rights HTTP/1.1
X-BCoT-Timestamp: 20180217T193337Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180217/ctn1_request, Signature=b6bf27017c8ee92da349f80e27e127f3c2cb3adeeeee28e19c18d9b9c3b752a8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
curl "https://sandbox.catenis.io/api/0.11/permission/events/receive-msg/rights" \
     -H 'X-BCoT-Timestamp: 20180217T193358Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180217/ctn1_request, Signature=6d2748f961de6714c16a0ff9096a9a9c2607778c2dc107d2f7492bc0878d2a81'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.retrievePermissionRights('receive-msg', function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Default (system) permission right:', data.system);

        if (data.catenisNode) {
            if (data.catenisNode.allow) {
                console.log('Index of Catenis nodes with \'allow\' permission right:', data.catenisNode.allow);
            }

            if (data.catenisNode.deny) {
                console.log('Index of Catenis nodes with \'deny\' permission right:', data.catenisNode.deny);
            }
        }

        if (data.client) {
            if (data.client.allow) {
                console.log('ID of clients with \'allow\' permission right:', data.client.allow);
            }

            if (data.client.deny) {
                console.log('ID of clients with \'deny\' permission right:', data.client.deny);
            }
        }

        if (data.device) {
            if (data.device.allow) {
                console.log('Devices with \'allow\' permission right:', data.device.allow);
            }

            if (data.device.deny) {
                console.log('Devices with \'deny\' permission right:', data.device.deny);
            }
        }
    }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.retrievePermissionRights('receive-msg', function (err, data) {
    if (err) {
        // Process error
    }
    else {
        // Process returned data
        console.log('Default (system) permission right:', data.system);

        if (data.catenisNode) {
            if (data.catenisNode.allow) {
                console.log('Index of Catenis nodes with \'allow\' permission right:', data.catenisNode.allow);
            }

            if (data.catenisNode.deny) {
                console.log('Index of Catenis nodes with \'deny\' permission right:', data.catenisNode.deny);
            }
        }

        if (data.client) {
            if (data.client.allow) {
                console.log('ID of clients with \'allow\' permission right:', data.client.allow);
            }

            if (data.client.deny) {
                console.log('ID of clients with \'deny\' permission right:', data.client.deny);
            }
        }

        if (data.device) {
            if (data.device.allow) {
                console.log('Devices with \'allow\' permission right:', data.device.allow);
            }

            if (data.device.deny) {
                console.log('Devices with \'deny\' permission right:', data.device.deny);
            }
        }
    }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->retrievePermissionRights('receive-msg');

    // Process returned data
    echo 'Default (system) permission right: ' . $data->system . PHP_EOL;

    if (isset($data->catenisNode)) {
        if (isset($data->catenisNode->allow)) {
            echo 'Index of Catenis nodes with \'allow\' permission right: ' . implode($data->catenisNode->allow, ', ') . PHP_EOL;
        }

        if (isset($data->catenisNode->deny)) {
            echo 'Index of Catenis nodes with \'deny\' permission right: ' . implode($data->catenisNode->deny, ', ') . PHP_EOL;
        }
    }

    if (isset($data->client)) {
        if (isset($data->client->allow)) {
            echo 'ID of clients with \'allow\' permission right: ' . implode($data->client->allow, ', ') . PHP_EOL;
        }

        if (isset($data->client->deny)) {
            echo 'ID of clients with \'deny\' permission right: ' . implode($data->client->deny, ', ') . PHP_EOL;
        }
    }

    if (isset($data->device)) {
        if (isset($data->device->allow)) {
            echo 'Devices with \'allow\' permission right: ' . print_r($data->device->allow, true);
        }

        if (isset($data->device->deny)) {
            echo 'Devices with \'deny\' permission right: ' . print_r($data->device->deny, true);
        }
    }
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let result = ctn_client.retrieve_permission_rights(
        PermissionEvent::ReceiveMsg,
    )?;

    println!("Default (system) permission right: {:?}", result.system);

    if let Some(rights_setting) = result.catenis_node {
        if let Some(catenis_node_idxs) = rights_setting.allow {
            println!(
                "Index of Catenis nodes with 'allow' permission right: {:?}",
                catenis_node_idxs
            );
        }

        if let Some(catenis_node_idxs) = rights_setting.deny {
            println!(
                "Index of Catenis nodes with 'deny' permission right: {:?}",
                catenis_node_idxs
            );
        }
    }

    if let Some(rights_setting) = result.client {
        if let Some(client_ids) = rights_setting.allow {
            println!("ID of clients with 'allow' permission right: {:?}", client_ids);
        }

        if let Some(client_ids) = rights_setting.deny {
            println!("ID of clients with 'deny' permission right: {:?}", client_ids);
        }
    }

    if let Some(rights_setting) = result.device {
        if let Some(devices) = rights_setting.allow {
            println!("Devices with 'allow' permission right: {:?}", devices);
        }

        if let Some(devices) = rights_setting.deny {
            println!("Devices with 'deny' permission right: {:?}", devices);
        }
    }

    Ok(())
}

Accessibility

Private

Request

GET /permission/events/:eventName/rights

Parameters

Sample response:

{
  "status": "success",
  "data": {
    "system": "deny",
    "client": {
      "allow": [
        "cjNhuvGMUYoepFcRZadP"
      ]
    },
    "device": {
      "allow": [
        {
          "deviceId": "dv3htgvK7hjnKx3617Re",
          "name": "Catenis device #1"
        }
      ]
    }
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  system String Permission right set at the system level.
  catenisNode Object (only returned if there are any permission rights set at the Catenis node level)
    allow Array(String) (only returned if not empty) List of Catenis node indices identifying the Catenis nodes to which allow right has been given.
    deny Array(String) (only returned if not empty) List of Catenis node indices identifying the Catenis nodes to which deny right has been given.
  client Object (only returned if there are any permission rights set at the client level)
    allow Array(String) (only returned if not empty) List of client IDs identifying the clients to which allow right has been given.
    deny Array(String) (only returned if not empty) List of client IDs identifying the clients to which deny right has been given.
  device Object (only returned if there are any permission rights set at the device level)
    allow Array(Object) (only returned if not empty) List of virtual device info objects identifying the devices to which allow right has been given.
      deviceId String The device ID of the virtual device.
      name String (only returned if virtual device has this data, and the virtual device issuing the request has the necessary permission right) The name of the virtual device.
      prodUniqueId String (only returned if virtual device has this data, and the virtual device issuing the request has the necessary permission right) The product unique ID of the virtual device.
    deny Array(Object) (only returned if not empty) List of virtual device info objects identifying the virtual devices to which deny right has been given.
      deviceId String The device ID of the virtual device.
      name String (only returned if virtual device has this data, and the virtual device issuing the request has the necessary permission right) The name of the virtual device.
      prodUniqueId String (only returned if virtual device has this data, and the virtual device issuing the request has the necessary permission right) The product unique ID of the virtual device.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
500 Internal server error
503 System currently not available; please try again at a later time

Send Message

Records a message on the blockchain directing it to another virtual device.

The virtual device that sends the message is referred to as the origin device, and the virtual device to which the message is sent is referred to as the target device.

Sample request:

POST /api/0.11/messages/send HTTP/1.1
X-BCoT-Timestamp: 20200122T200146Z
Authorization: CTN1-HMAC-SHA256 Credential=d8YpQ7jgPBJEkBrnvp58/20200122/ctn1_request, Signature=bb952d55523490deb8dafd2c0f7d7acaf71959026fa844a2fa36de1084d3d54c
Content-Type: application/json; charset=utf-8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.10 (Macintosh; OS X/10.15.2) GCDHTTPRequest
Content-Length: 180

{"message":"This is only a test","targetDevice":{"id":"dv3htgvK7hjnKx3617Re"},"options":{"encoding":"utf8","encrypt":true,"offChain":true,"storage":"auto","readConfirmation":true}}
curl -X "POST" "http://localhost:3000/api/0.11/messages/send" \
     -H 'X-BCoT-Timestamp: 20200122T200220Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=d8YpQ7jgPBJEkBrnvp58/20200122/ctn1_request, Signature=406727fab045ade27eb6fa87012698b542aca4a44b889951dee249b05350b3b9' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "message": "This is only a test",
  "options": {
    "encoding": "utf8",
    "encrypt": true,
    "offChain": true,
    "storage": "auto",
    "readConfirmation": true
  },
  "targetDevice": {
    "id": "dv3htgvK7hjnKx3617Re"
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var targetDevice = {
    id: 'dv3htgvK7hjnKx3617Re'
}

ctnApiClient.sendMessage('This is only a test', targetDevice, {
        encoding: 'utf8',
        encrypt: true,
        offChain: true,
        storage: 'auto',
        readConfirmation: true
    },
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('ID of sent message:', data.messageId);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var targetDevice = {
    id: 'dv3htgvK7hjnKx3617Re'
}

ctnApiClient.sendMessage(targetDevice, 'This is only a test', {
        encoding: 'utf8',
        encrypt: true,
        offChain: true,
        storage: 'auto',
        readConfirmation: true
    },
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('ID of sent message:', data.messageId);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$targetDevice = [
  'id' => 'dv3htgvK7hjnKx3617Re'
];

try {
    $data = $ctnApiClient->sendMessage($targetDevice, 'My message to send', [
        'encoding' => 'utf8',
        'encrypt' => true,
        'offChain' => true,
        'storage' => 'auto',
        'readConfirmation' => true
    ]);

    // Process returned data
    echo 'ID of sent message: ' . $data->messageId . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let target_device = DeviceId {
        id: String::from("dv3htgvK7hjnKx3617Re"),
        is_prod_unique_id: None,
    };

    let result = ctn_client.send_message(
        Message::Whole(String::from("This is only a test")),
        target_device,
        Some(SendMessageOptions {
            encoding: Some(Encoding::UTF8),
            encrypt: Some(true),
            off_chain: Some(true),
            storage: Some(Storage::Auto),
            read_confirmation: Some(true),
            async_: None,
        }),
    )?;

    println!("ID of sent message: {}", result.message_id.unwrap());

    Ok(())
}

Accessibility

Private

Request

POST /messages/send

Parameters

A JSON containing the following properties:

Property Type Description
message String|Object The message to send. If an object is passed instead, it is expected that the message be passed in chunks.
  data String (optional) The next message data chunk. The actual message's contents should be comprised of one or more data chunks.
  isFinal Boolean (optional, default: true) Indicates whether this is the final message data chunk.
  continuationToken String (optional) Indicates that this is a continuation message data chunk. It should be filled with the value returned in the continuationToken field of the response to the request used to pass the previous message data chunk.
targetDevice Object
  id String The ID of the virtual device to which the message is directed. Should be a device ID unless isProdUniqueId is set.
  isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.
options Object (optional)
  encoding String (optional, default: utf8) Value identifying the encoding of the message. Valid options: utf8, base64, hex.
  encrypt Boolean (optional, default: true) Indicates whether message should be encrypted before storing it.
  offChain Boolean (optional, default: true) Indicates whether message should be sent as a Catenis off-chain message.
  storage String (optional, default: auto) Value identifying where the message should be stored. Valid options: auto, embedded, external. The value embedded specifies that the message should be stored on the blockchain transaction itself; the value external specifies that the message should be stored in an external repository; and the value auto is used to specify that the message be embedded whenever possible otherwise it should be stored in the external storage.
  readConfirmation Boolean (optional, default: false) Indicates whether message should be sent with read confirmation enabled. This should be used when the origin device intends to be notified when the target device first reads the message.
  async Boolean (optional, default: false) Indicates whether processing — storage of message to the blockchain — should be done asynchronously.

Sample response:

{
  "status": "success",
  "data": {
    "messageId": "ouczbRbcgo3F8XoC6ejE"
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  continuationToken String (only returned if passing message in chunks and last message data chunk was not final) Token to be used when sending the following message data chunk.
  messageId String (only returned after message has been processed) ID of the sent message.
  provisionalMessageId String (only returned if doing asynchronous processing after the whole message's contents are passed) ID of provisional message.

Possible errors

Status code Error message
400 Invalid or unexpected continuation token
Invalid parameters: <param_list>
Invalid target device
Message already complete
Message expired
Message too long to be embedded
Not enough credits to pay for send message service
413 Request data too large to be processed
500 Internal server error
503 System currently not available; please try again at a later time

Set Permission Rights

Sets permission rights at different levels for a specific permission event.

The virtual device issuing the request acts as the controlling device. Thus the permission rights are set for the pair composed of the permission event specified in the API request and the virtual device issuing the request.

Sample request:

POST /api/0.11/permission/events/receive-msg/rights HTTP/1.1
X-BCoT-Timestamp: 20180217T201833Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180217/ctn1_request, Signature=df048c4f799dbc0b15b7b105313b9c134d499eb330ecf1ee2b27b5319c89bb86
Content-Type: application/json; charset=utf-8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest
Content-Length: 147

{"client":{"allow":"self","deny":"cjNhuvGMUYoepFcRZadP"},"device":{"allow":[{"id":"dv3htgvK7hjnKx3617Re"},{"id":"XYZ0001","isProdUniqueId":true}]}}
curl -X "POST" "https://sandbox.catenis.io/api/0.11/permission/events/receive-msg/rights" \
     -H 'X-BCoT-Timestamp: 20180217T201855Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180217/ctn1_request, Signature=d52d99ab524ee9f6ed7ca4d96c0041ff9ba7ca1540497dc527c51596da98a27a' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "client": {
    "allow": "self",
    "deny": "cjNhuvGMUYoepFcRZadP"
  },
  "device": {
    "allow": [
      {
        "id": "dv3htgvK7hjnKx3617Re"
      },
      {
        "id": "XYZ0001",
        "isProdUniqueId": true
      }
    ]
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.setPermissionRights('receive-msg', {
        client: {
            allow: 'self'
            deny: 'cjNhuvGMUYoepFcRZadP'
        },
        device: {
            allow: [{
                id: 'dv3htgvK7hjnKx3617Re'
            }, {
                id: 'XYZ0001',
                isProdUniqueId: true
            }]
        }
    },
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Permission rights successfully set');
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

ctnApiClient.setPermissionRights('receive-msg', {
        client: {
            allow: 'self'
            deny: 'cjNhuvGMUYoepFcRZadP'
        },
        device: {
            allow: [{
                id: 'dv3htgvK7hjnKx3617Re'
            }, {
                id: 'XYZ0001',
                isProdUniqueId: true
            }]
        }
    },
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Permission rights successfully set');
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

try {
    $data = $ctnApiClient->setPermissionRights('receive-msg', [
        'client' => [
            'allow' => 'self',
            'deny' => 'cjNhuvGMUYoepFcRZadP'
        ],
        'device' => [
            'allow' => [[
                'id' => 'dv3htgvK7hjnKx3617Re'
            ], [
                'id' => 'XYZ0001',
                'isProdUniqueId' => true
            ]]
        ]
    ]);

    // Process returned data
    echo 'Permission rights successfully set' . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let _result = ctn_client.set_permission_rights(
        PermissionEvent::ReceiveMsg,
        AllPermissionRightsUpdate {
            system: None,
            catenis_node: None,
            client: Some(PermissionRightsUpdate {
                allow: Some(vec![
                    String::from("self"),
                ]),
                deny: Some(vec![
                    String::from("cjNhuvGMUYoepFcRZadP"),
                ]),
                none: None,
            }),
            device: Some(DevicePermissionRightsUpdate {
                allow: Some(vec![
                    DeviceId {
                        id: String::from("dv3htgvK7hjnKx3617Re"),
                        is_prod_unique_id: None,
                    },
                    DeviceId {
                        id: String::from("XYZ0001"),
                        is_prod_unique_id: Some(true),
                    },
                ]),
                deny: None,
                none: None,
            }),
        },
    )?;

    println!("Permission rights successfully set");

    Ok(())
}

Accessibility

Private

Request

POST /permission/events/:eventName/rights

Parameters

A JSON containing the following properties:

Property Type Description
system String (optional) Permission right to be set at the system level. Valid options: allow, deny.
catenisNode Object (optional) Permission rights to be set at the Catenis node level.
  allow String|Array(String) (optional) A single Catenis node index or a list of Catenis node indices identifying the Catenis nodes to which allow right should be given. The special value self can be used in place of the index of the Catenis node where the client to which the virtual device issuing the request belongs is defined.
  deny String|Array(String) (optional) A single Catenis node index or a list of Catenis node indices identifying the Catenis nodes to which deny right should be given. The special value self can be used in place of the index of the Catenis node where the client to which the virtual device issuing the request belongs is defined.
  none String|Array(String) (optional) A single Catenis node index or a list of Catenis node indices identifying the Catenis nodes the rights of which should be removed. The special value self can be used in place of the index of the Catenis node where the client to which the virtual device issuing the request belongs is defined. The special wildcard character * can also be used to indicate that the rights for all Catenis nodes should be remove.
client Object (optional) Permission rights to be set at the client level.
  allow String|Array(String) (optional) A single client ID or a list of client IDs identifying the clients to which allow right should be given. The special value self can be used in place of the client ID of the client to which the virtual device issuing the request belongs.
  deny String|Array(String) (optional) A single client ID or a list of client IDs identifying the clients to which deny right should be given. The special value self can be used in place of the client ID of the client to which the virtual device issuing the request belongs.
  none String|Array(String) (optional) A single client ID or a list of client IDs identifying the clients the rights of which should be removed. The special value self can be used in place of the client ID of the client to which the virtual device issuing the request belongs. The special wildcard character * can also be used to indicate that the rights for all clients should be remove.
device Object (optional) Permission rights to be set at the device level.
  allow Object|Array(Object) (optional) A single virtual device info object or a list of virtual device info objects identifying the virtual devices to which allow right should be given.
    id String (optional) The ID of the virtual device. Should be a device ID unless isProdUniqueId is set. The special value self can be used in place of the device ID of the virtual device issuing the request.
    isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.
  deny Object|Array(Object) (optional) A single virtual device info object or a list of virtual device info objects identifying the virtual devices to which deny right should be given.
    id String (optional) The ID of the virtual device. Should be a device ID unless isProdUniqueId is set. The special value self can be used in place of the device ID of the virtual device issuing the request.
    isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.
  none Object|Array(Object) (optional) A single virtual device info object or a list of virtual device info objects identifying the virtual devices the rights of which should be removed.
    id String (optional) The ID of the virtual device. Should be a device ID unless isProdUniqueId is set. The special value self can be used in place of the device ID of the virtual device issuing the request. The special wildcard character * can also be used to indicate that the rights for all devices should be remove.
    isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.

Sample response:

{
  "status": "success",
  "data": {
    "success": true
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  success Boolean The value true indicating that the permission rights have been correctly set.

Possible errors

Status code Error message
400 Invalid parameters: <param_list>
Invalid entity ID: [ctnNodeIdx: …][; clientId: …][; deviceId: …][; prodUniqueId: …]
500 Internal server error
503 System currently not available; please try again at a later time

Transfer Asset

Transfers an amount of an asset to a device.

Sample request:

POST /api/0.11/assets/aQjlzShmrnEZeeYBZihc/transfer/ HTTP/1.1
X-BCoT-Timestamp: 20180417T132059Z
Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=44e21bb5c895eceafce0910a27d0879e3be7dcff278c07a01597f09e6c0bb317
Content-Type: application/json; charset=utf-8
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.4) GCDHTTPRequest
Content-Length: 64

{"amount":54.25,"receivingDevice":{"id":"dv3htgvK7hjnKx3617Re"}}
curl -X "POST" "https://sandbox.catenis.io/api/0.11/assets/aQjlzShmrnEZeeYBZihc/transfer/" \
     -H 'X-BCoT-Timestamp: 20180417T132027Z' \
     -H 'Authorization: CTN1-HMAC-SHA256 Credential=dnN3Ea43bhMTHtTvpytS/20180417/ctn1_request, Signature=17bb4e914bd10aa517d15df1c985f0e9604a660a3a146219e16a1c94a8f7bf93' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "amount": 54.25,
  "receivingDevice": {
    "id": "dv3htgvK7hjnKx3617Re"
  }
}'
<script src="CatenisAPIClientJS.min.js"></script>

<script language="JavaScript">
var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';
var receivingDevice = {
    id: 'dv3htgvK7hjnKx3617Re'
};

ctnApiClient.transferAsset(assetId, 54.25, receivingDevice,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Remaining asset balance:', data.remainingBalance);
        }
});
</script>
var CtnApiClient = require('catenis-api-client');

var deviceId = 'dnN3Ea43bhMTHtTvpytS';

var ctnApiClient = new CtnApiClient(deviceId, apiAccessSecret, {
    environment: 'sandbox'
});

var assetId = 'aQjlzShmrnEZeeYBZihc';
var receivingDevice = {
    id: 'dv3htgvK7hjnKx3617Re'
};

ctnApiClient.transferAsset(assetId, 54.25, receivingDevice,
    function (err, data) {
        if (err) {
            // Process error
        }
        else {
            // Process returned data
            console.log('Remaining asset balance:', data.remainingBalance);
        }
});
<?php
require __DIR__ . '/vendor/autoload.php';

use Catenis\ApiClient;
use Catenis\Exception\CatenisException;

$deviceId = 'dnN3Ea43bhMTHtTvpytS';

$ctnApiClient = new ApiClient($deviceId, $apiAccessSecret, [
    'environment' => 'sandbox'
]);

$assetId = 'aQjlzShmrnEZeeYBZihc';
$receivingDevice = [
   'id' => 'dv3htgvK7hjnKx3617Re'
];

try {
    $data = $ctnApiClient->transferAsset($assetId, 54.25, $receivingDevice);

    // Process returned data
    echo 'Remaining asset balance: ' . $data->remainingBalance . PHP_EOL;
}
catch (CatenisException $ex) {
    // Process exception
}
use catenis_api_client::{
    CatenisClient, ClientOptions, Environment, Result,
    api::*,
};

fn main() -> Result<()> {
    let device_credentials = (
        "dnN3Ea43bhMTHtTvpytS",
        concat!(
        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
        "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
        ),
    ).into();

    let mut ctn_client = CatenisClient::new_with_options(
        Some(device_credentials),
        &[
            ClientOptions::Environment(Environment::Sandbox),
        ],
    )?;

    let asset_id = "aQjlzShmrnEZeeYBZihc";
    let receiving_device = DeviceId {
        id: String::from("dv3htgvK7hjnKx3617Re"),
        is_prod_unique_id: None,
    };

    let result = ctn_client.transfer_asset(
        asset_id,
        54.25,
        receiving_device,
    )?;

    println!("Remaining asset balance: {}", result.remaining_balance);

    Ok(())
}

Accessibility

Private

Request

POST /assets/:assetId/transfer

Parameters

A JSON containing the following properties:

Property Type Description
amount Number The amount of asset to transfer.
receivingDevice Object Virtual device to which the asset is to be transferred.
  id String The ID of the receiving device. Should be a device ID unless isProdUniqueId is set.
  isProdUniqueId Boolean (optional, default: false) Indicates whether the supplied ID is a product unique ID.

Sample response:

{
  "status": "success",
  "data": {
    "remainingBalance": 1145.75
  }
}

Success response

A JSON containing the following properties:

Property Type Description
status String The value success, indicating that the request was successful.
data Object The actual data returned in response to the API request.
  remainingBalance Number Total balance of the asset still held by the device that issued the request after the transfer.

Possible errors

Status code Error message
400 Amount to transfer is too large
Insufficient balance to transfer asset
Invalid asset ID
Invalid parameters: <param_list>
Invalid receiving device
Not enough credits to pay for transfer asset service
403 No permission to transfer asset to receiving device
500 Internal server error
503 System currently not available; please try again at a later time

Notifications

Catenis provides a notification service where a virtual device can receive a real-time message notifying that a given predefined event that concerns it has taken place. Such predefined events are referred to as notification events.

Notification events

The following notification events are currently defined:

Event name Description
new-msg-received A new message has been received
sent-msg-read Previously sent message has been read by intended receiver (target device)
asset-received An amount of an asset has been received
asset-confirmed An amount of an asset that was pending due to an asset transfer has been confirmed
final-msg-progress Progress of asynchronous message processing has come to an end
asset-export-outcome Asset export has been finalized
asset-migration-outcome Asset migration has been finalized

Notification messages

The Catenis notifications are conveyed by means of notification messages the contents of which vary according to the notification event, as follows:

New message received (new-msg-received)

Sample notification message:

{
  "messageId": "mNEWqgSMAeDAmBAkBDWr",
  "from": {
    "deviceId": "dnN3Ea43bhMTHtTvpytS",
    "name": "deviceB",
    "prodUniqueId": "XYZABC001"
  },
  "receivedDate": "2018-01-29T23:27:39.657Z"
}

A JSON containing the following properties:

Property Type Description
messageId String The ID of the received message.
from Object Identifies the virtual device that sent the received message — the origin device.
  deviceId String The device ID of the origin device.
  name String (only returned if origin device has this data, and the device receiving the notification has the necessary permission right) The name of the origin device.
  prodUniqueId String (only returned if origin device has this data, and the device receiving the notification has the necessary permission right) The product unique ID of the origin device.
receivedDate String ISO 8601 formatted date and time when the message has been received.

Sent message read (sent-msg-read)

Sample notification message:

{
  "messageId": "mNEWqgSMAeDAmBAkBDWr",
  "to": {
    "deviceId": "dv3htgvK7hjnKx3617Re",
    "name": "Catenis device #1"
  },
  "readDate": "2018-01-30T01:02:12.162Z"
}

A JSON containing the following properties:

Property Type Description
messageId String The ID of the read message.
to Object Identifies the virtual device to which the read message had been sent — the target device.
  deviceId String The device ID of the target device.
  name String (only returned if target device has this data, and the device receiving the notification has the necessary permission right) The name of the target device.
  prodUniqueId String (only returned if target device has this data, and the device receiving the notification has the necessary permission right) The product unique ID of the target device.
readDate String ISO 8601 formatted date and time when the message has been read.

Asset amount received (asset-received)

Sample notification message:

{
  "assetId": "aQjlzShmrnEZeeYBZihc",
  "issuer": {
    "deviceId": "dnN3Ea43bhMTHtTvpytS",
    "name": "deviceB",
    "prodUniqueId": "XYZABC001"
  },
  "from": {
    "deviceId": "dv3htgvK7hjnKx3617Re",
    "name": "Catenis device #1"
  },
  "receivedDate": "2018-04-01T17:15:36.134Z"
}

A JSON containing the following properties:

Property Type Description
assetId String The ID of the received asset.
amount Amount The amount of the asset that has been received.
issuer Object Identifies the virtual device that issued the asset — the issuing device.
  deviceId String The device ID of the issuing device.
  name String (only returned if issuing device has this data, and the device receiving the notification has the necessary permission right) The name of the issuing device.
  prodUniqueId String (only returned if issuing device has this data, and the device receiving the notification has the necessary permission right) The product unique ID of the issuing device.
from Object Identifies the virtual device that sent or assigned the asset amount — the sending device.
  deviceId String The device ID of the sending device.
  name String (only returned if sending device has this data, and the device receiving the notification has the necessary permission right) The name of the sending device.
  prodUniqueId String (only returned if sending device has this data, and the device receiving the notification has the necessary permission right) The product unique ID of the sending device.
receivedDate String ISO 8601 formatted date and time when the asset amount has been received.

Asset amount confirmed (asset-confirmed)

Sample notification message:

{
  "assetId": "aQjlzShmrnEZeeYBZihc",
  "amount": 54.25,
  "issuer": {
    "deviceId": "dnN3Ea43bhMTHtTvpytS",
    "name": "deviceB",
    "prodUniqueId": "XYZABC001"
  },
  "from": {
    "deviceId": "dv3htgvK7hjnKx3617Re",
    "name": "Catenis device #1"
  },
  "confirmedDate": "2018-04-01T17:32:03.012Z"
}

A JSON containing the following properties:

Property Type Description
assetId String The ID of the confirmed asset.
amount Amount The amount of the asset that has been confirmed.
issuer Object Identifies the virtual device that issued the asset — the issuing device.
  deviceId String The device ID of the issuing device.
  name String (only returned if issuing device has this data, and the device receiving the notification has the necessary permission right) The name of the issuing device.
  prodUniqueId String (only returned if issuing device has this data, and the device receiving the notification has the necessary permission right) The product unique ID of the issuing device.
from Object Identifies the virtual device that originally sent or assigned the asset amount — the sending device.
  deviceId String The device ID of the sending device.
  name String (only returned if sending device has this data, and the device receiving the notification has the necessary permission right) The name of the sending device.
  prodUniqueId String (only returned if sending device has this data, and the device receiving the notification has the necessary permission right) The product unique ID of the sending device.
confirmedDate String ISO 8601 formatted date and time when the asset amount has been confirmed.

Final progress of message processing (final-msg-progress)

Sample notification message:

{
  "ephemeralMessageId": "hEXMdtTMzkhyJ4WssQmp",
  "action": "read",
  "progress": {
    "bytesProcessed": 28,
    "done": true,
    "success": true,
    "finishDate": "2019-03-13T14:09:10.121Z"
  },
  "result": {
    "messageId": "mt7ZYbBYpM3zcgAf3H8X",
    "continuationToken": "kjXP2CZaSdkTKCi2jDi2"
  }
}

A JSON containing the following properties:

Property Type Description
ephemeralMessageId String The ID of the ephemeral message — either a provisional or a cached message — to which this notification refers.
action String The action that was to be performed on the message. One of: log, send, or read.
progress Object Current processing status.
  bytesProcessed Number Total number of bytes of message that had already been processed.
  done Boolean (should always be true) Indicates that processing has finished.
  success Boolean Indicates whether message has been successfully processed.
  error Object (only returned if processing finished with error) Error information.
    code Number Numeric code — equivalent to an HTML status code — of the error that took place while processing the message.
    message String Text describing the error that took place while processing the message.
  finishDate String ISO 8601 formatted date and time when processing was finalized.
result Object (only returned if processing finished successfully) Result of processing.
  messageId String ID of the Catenis message. When logging or sending — action equals to log or send—, it is the ID of the resulting message. When reading — action equals to read—, it references the message being read.
  continuationToken String (only returned if reading message — action equals to read) The token that should be used to complete the read of the message.

Final asset export outcome (asset-export-outcome)

Sample notification message:

{
  "assetId": "amNiawM69NjYM8QghoPD",
  "foreignBlockchain": "ethereum",
  "foreignTransaction": {
    "isPending": false,
    "success": true,
    "txid": "0x1738722379007192cac3b8e7ee3babfd1c8304133ea1a7957b93f6134ed62e48"
  },
  "token": {
    "name": "Catenis test token #5",
    "symbol": "CTK5",
    "id": "0xbAE69964D40900c6933A2CF8dD53f97c97Ab9BE7"
  },
  "status": "success",
  "date": "2021-07-02T21:26:33.841Z"
}

A JSON containing the following properties:

Property Type Description
assetId String The ID of the exported asset.
foreignBlockchain String The key identifying the foreign blockchain to where the asset has been exported. One of: ethereum, binance, or polygon.
foreignTransaction Object Information about the transaction issued on the foreign blockchain to create the resulting foreign token.
  txid String The ID (or hash) of the foreign blockchain transaction.
  isPending Boolean The value false, indicating that the foreign blockchain transaction has already been executed.
  success Boolean Indicates whether the foreign blockchain transaction has been successfully executed or not.
  error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
token Object Information about the resulting foreign token.
  name String The token name.
  symbol String The token symbol.
  id String (only returned if the asset is successfully export) The ID (or address) of the token on the foreign blockchain.
status String The final state of the asset export. One of: success, or error.
date String ISO 8601 formatted date and time when the asset has been exported.

Final asset migration outcome (asset-migration-outcome)

Sample notification message:

{
  "migrationId": "gbRQqs5z3ReCGfygorai",
  "assetId": "amNiawM69NjYM8QghoPD",
  "foreignBlockchain": "ethereum",
  "direction": "outward",
  "amount": 50,
  "catenisService": {
    "status": "fulfilled",
    "txid": "823941a1e02eab77d5ceecc943d7745bc49068f35d4109f7d60f9ca6fc669838"
  },
  "foreignTransaction": {
    "isPending": false,
    "success": true,
    "txid": "0x098d5588d03db577edfc8fc5b0094a62e22825bc9c7fc8e38430563350c75bfd"
  },
  "status": "success",
  "date": "2021-07-03T12:51:04.771Z"
}

A JSON containing the following properties:

Property Type Description
migrationId String The ID of the asset migration.
assetId String The ID of the asset the amount of which has been migrated.
foreignBlockchain String The key identifying the foreign blockchain to/from where the asset amount has been migrated. One of: ethereum, binance, or polygon.
direction String The direction of the migration. One of: outward or inward.
amount Number The migrated asset amount.
catenisService Object Information about the execution of the migrate asset Catenis service.
  status String The current state of the service's execution. One of: awaiting, failure, or fulfilled.
  txid String (only returned if the service is successfully fulfilled) The ID of the Catenis transaction issued to fulfill the service.
  error String (only returned if the service's execution has failed) An error message describing what went wrong when executing the service.
foreignTransaction Object Information about the transaction issued on the foreign blockchain to mint/burn the amount of the foreign token.
  txid String The ID (or hash) of the foreign blockchain transaction.
  isPending Boolean The value false, indicating that the foreign blockchain transaction has already been executed.
  success Boolean Indicates whether the foreign blockchain transaction has been successfully executed or not.
  error String (only returned if the foreign blockchain transaction's execution has failed) An error message describing what went wrong when executing the transaction.
status String The final state of the asset migration. One of: interrupted, success, or error.
date String ISO 8601 formatted date and time when the asset amount has been migrated.

Notification channel

To be able to receive notifications, a virtual device must open a notification channel for a specific notification event. Then, as long as the notification channel is open, the virtual device shall receive notification messages when the corresponding event takes place.

The way that a notification channel is open depends on the notification message dispatcher used.

The following notification message dispatchers are currently available:

WebSocket notification message dispatcher

This notification message dispatcher uses a WebSocket connection as the communication transport for the notification channel.

To open a notification channel, one needs to establish a WebSocket connection using the information provided below.

Connection endpoint URL

Sandbox environment: wss://sandbox.catenis.io/api/0.11/notify/ws/:eventName

Parameters

WebSocket subprotocol

notify.catenis.io

Authentication

The following steps should be taken in order to successfully authenticate the virtual device when establishing a WebSocket connection to open the notification channel:

Sample authenticated dummy WebSocket notification request:

GET /api/0.11/notify/ws/new-msg-received HTTP/1.1
X-BCoT-Timestamp: 20180219T223932Z
Authorization: CTN1-HMAC-SHA256 Credential=dmM2Dz32agLSGsSuoxsR/20180219/ctn1_request, Signature=59b44f3d504b272e92c1f96694b7f6abb39b8cb7726ffe8b57d2cb46aedf568b
Host: sandbox.catenis.io
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.13.3) GCDHTTPRequest

Sample WebSocket authentication message:

{
  "x-bcot-timestamp": "20180219T223932Z",
  "authorization": "CTN1-HMAC-SHA256 Credential=dmM2Dz32agLSGsSuoxsR/20180219/ctn1_request, Signature=59b44f3d504b272e92c1f96694b7f6abb39b8cb7726ffe8b57d2cb46aedf568b"
}
  1. Assemble a dummy GET request using the WebSocket notification channel URL, and then authenticate it as if it was a regular Catenis API request — for more information about API request authentication, please refer to the Authentication section above.

  2. Do not send the authenticated request, but rather just take the HTTP headers X-BCoT-Timestamp and Authorization contained in it and save them.

  3. Go ahead and open the WebSocket connection.

  4. Right after the WebSocket connection is open, send a single message the contents of which should be a JSON containing the following properties:

Property Type Description
x-bcot-timestamp String The value of the X-BCoT-Timestamp HTTP header saved at step 3 above.
authorization String The value of the Authorization HTTP header saved at step 3 above.

Authentication response

If a successful authentication message is not received by the WebSocket message dispatcher within 5 seconds after the WebSocket connection is established, the WebSocket connection is closed by the Catenis server.

Notification Channel Open message

After receiving a successful authentication message, the WebSocket message dispatcher will send a special message the content of which is NOTIFICATION_CHANNEL_OPEN.

This message is used to confirm that the WebSocket notification channel is open and ready to send notifications.

Errors

Catenis uses conventional HTTP response status codes to indicate the general outcome of an API request.

HTTP status codes

The following HTTP status codes are returned by the Catenis API.

Status code Explanation
200 OK - The request succeeded.
400 Bad Request - The request could not be processed the way it was, and should be changed before it is resubmitted.
401 Unauthorized - The request requires user authentication, or authorization has been refused for the supplied credentials.
403 Forbidden - The request cannot be fulfilled.
413 Payload Too Large - The data sent with the request is too large and cannot be processed.
500 Internal Server Error - The server encountered an unexpected condition which prevented it from fulfilling the request.
503 Service Unavailable - The server is currently unable to handle the request.

Error response

Error response:

{
  "status": "error",
  "message": "Invalid parameters"
}

To better describe the condition that led to the error, a JSON with the following properties is returned for all failed API requests.

Property Type Description
status String The value error, indicating that the request has failed.
message String Error message

Error messages

The following is a comprehensive list of the error messages returned by the Catenis API.

Error message Explanation
Amount to issue is too large The specified amount of asset to be issued is larger than the largest allowed amount (2^53 - 1), or the total available amount of the asset, after the issuance, would be larger than the largest allowed amount.
Amount to migrate is too large The specified amount of asset to be migrated is larger than the largest allowed amount (2^53 - 1).
Amount to transfer is too large The specified amount of asset to be transferred is larger than the largest allowed amount (2^53 - 1).
Asset already exported The asset that one wants to export is already exported.
Asset cannot be reissued The specified asset does not allow for additional quantities of it to be issued after its first issuance.
Asset is not yet exported The asset that one wants to migrate an amount of it or to retrieve its outcome is not yet exported.
Asset migration already successfully processed The asset migration that one wants to reprocess has already been successfully processed.
Authorization failed; authorization value not well formed Request could not be authorized because the contents of the Authorization HTTP header is not as expected.
Authorization failed; invalid device or signature Request could not be authorized because the device ID and/or the signature included in the credentials (Authorization header contents) are not valid. Note that a deleted or inactive device will trigger this error.
Authorization failed; missing required HTTP headers Request could not be authorized because one or more of the required HTTP headers are missing.
Authorization failed; signature date not well formed Request could not be authorized because the format of the date included in the credentials (Authorization header contents) is not correct.
Authorization failed; signature date out of bounds Request could not be authorized because the date included in the credentials (Authorization header contents) is not within 7 days of the current date.
Authorization failed; timestamp not well formed Request could not be authorized because the contents of the X-BCoT-Timestamp HTTP header is not a valid timestamp or it is not in the correct format.
Authorization failed; timestamp not within acceptable time variation Request could not be authorized because its timestamp (X-BCoT-Timestamp header contents) is not within +/-5 minutes of the current Catenis server time.
Discarded concurrent foreign token smart contract call The foreign blockchain transaction was discarded because it had a repeated nonce.
Foreign blockchain funds not enough to cover transaction execution price (<value>) The foreign blockchain's native coin balance of the virtual device's client foreign blockchain asset export admin account is too low to pay for the foreign blockchain transaction's execution price.
Foreign token balance too low to in-migrate the asset amount The virtual device's client foreign blockchain asset export admin account does not currently hold a large enough quantity of the foreign token to fulfill the in-migration.
Insufficient balance to out-migrate asset The virtual device does not currently hold a large enough quantity of the asset to fulfill the out-migration.
Insufficient balance to transfer asset The virtual device does not currently hold a large enough quantity of the asset to fulfill the transfer.
Insufficient migrated asset amount to in-migrate asset The total out-migrated amount of the specified asset is not large enough to fulfill the in-migration.
Internal server error An unexpected situation prevented Catenis from correctly processing the request.
Invalid asset ID The supplied asset ID is invalid or no asset with that ID could be found.
Invalid asset migration ID The supplied asset migration ID is invalid or no asset migration with that ID could be found.
Invalid device The supplied ID is not a valid device ID or product unique ID, or there is no virtual device with that ID.
Invalid entity ID: [ctnNodeIdx: …][; clientId: …][; deviceId: …][; prodUniqueId: …] One or more of the supplied entity IDs (Catenis Node index, client ID, device ID, or product unique ID) are not valid or there are no entities (Catenis Node, client, or virtual device) with those IDs.
Invalid foreign blockchain destination address The supplied destination address is not a valid foreign blockchain account address.
Invalid holding device The ID (either the device ID or the product unique ID) of the virtual device to hold the issued asset amount is not valid or there is no virtual device with that ID.
Invalid message ID The supplied message ID is invalid or no message with that ID could be found.
Invalid or expired ephemeral message The supplied ID is not of a valid ephemeral message, or the asynchronous processing status cannot be retrieved for the given ephemeral message.
Invalid or unexpected continuation token The supplied ID is not a valid continuation token, or that is not the ID that Catenis expects to continue processing the message.
Invalid parameters: <param_list> The listed parameters are not well formed or are missing.
Invalid receiving device The ID (either the device ID or the product unique ID) of the virtual device to receive the transferred assets is not valid or there is no virtual device with that ID.
Invalid target device The ID (either the device ID or the product unique ID) of the virtual device to receive the message is not valid or there is no virtual device with that ID.
Message already complete Catenis has already received the full message's contents, and an additional message chunk cannot be accepted.
Message already read The message, which has been requested to be read asynchronously or in chunks, has already been fully read.
Message expired The maximum time expected for the next message chunk to be passed/retrieved has elapsed and Catenis cannot fulfill the request.
Message not available The message, which has been requested to be read asynchronously, is not yet ready to be read.
Message origin cannot be disclosed The message's origin device does not allow the disclosure of information about it.
Message too large for reading at once The contents of the message being read is too large for Catenis to returned it in a single call.
Message too long to be embedded Request specified that message should be stored embedded in the blockchain transaction but it is too large (over 75 bytes unencrypted or 64 bytes encrypted) to fit in.
Mismatched asset migration The specified asset migration does not correspond to the specified asset and/or foreign blockchain.
No permission to assign issued asset to holding device The virtual device has no permission to assign the amount of the asset to be issued to the specified holding device.
No permission to export asset The virtual device attempting to export the asset is not the device that issued that asset.
No permission to list asset holders The virtual device has no permission to list holders of the requested asset.
No permission to migrate asset The virtual device attempting to migrate the asset amount is not the device that exported that asset.
No permission to read message The virtual device has no permission to read the requested message.
No permission to reissue asset The virtual device attempting to issue an additional quantity of the asset is not the device that issued the initial amount of that asset.
No permission to retrieve asset export outcome The virtual device attempting to retrieve information about an asset export outcome is not the device that issued that asset export.
No permission to retrieve asset info The virtual device has no permission to retrieve information about the requested asset.
No permission to retrieve asset issuance history The virtual device has no permission to retrieve issuance history of the requested asset.
No permission to retrieve asset migration outcome The virtual device attempting to retrieve information about an asset migration outcome is not the device that issued that asset migration.
No permission to retrieve info The virtual device has no permission to retrieve information about the requested device.
No permission to retrieve message container The virtual device attempting to retrieve the message container information is not the device that sent/logged the message.
No permission to transfer asset to receiving device The virtual device has no permission to transfer an amount of the asset to the specified receiving device.
Not enough credits to pay for issue asset service The virtual device's client service account balance is too low to cover the issue asset service's expense.
Not enough credits to pay for log message service The virtual device's client service account balance is too low to cover the log message service's expense.
Not enough credits to pay for migrate asset service The virtual device's client service account balance is too low to cover the migrate asset service's expense.
Not enough credits to pay for send message service The virtual device's client service account balance is too low to cover the send message service's expense.
Not enough credits to pay for transfer asset service The virtual device's client service account balance is too low to cover the transfer asset service's expense.
Progress not available Asynchronous processing status not yet available for the given ephemeral message.
Request data too large to be processed Catenis refuses to process the request because the data sent with the request (typically a message's contents) is too large.
System currently not available; please try again at a later time Catenis is not currently ready to process requests.
Unexpected error calling foreign token smart contract An unexpected error prevented the foreign blockchain transaction to be executed.