NAV
javascript

Sygna Bridge

API Design Principles

API Request and Response

REST-like API - Simple and predictable URLs to access data. The Sygna Bridge APIs uses GET and POST, and HTTP responses are UTF-8 encoded JSON objects.

Securing the APIs by using HTTPS

Hypertext Transfer Protocol Secure (HTTPS) is a variant of the standard web transfer protocol (HTTP) that adds a layer of security on the data in transit through the SSL/TLS protocol connection. Sygna Bridge APIs use HTTPS to provide a stronger guarantee that a VASP is communicating with the real API and receiving back authentic content. It also enhances privacy for applications and VASPs using the API.

Callback APIs

VASPs require best-time updates and should avoid busy-waiting for the other party's compliance validation. We use a callback method to work around this issue and flag the VASP so it can proceed.

The beneficiary server can take as long as it needs to validate the permission request. When it finishes the validation, it will post the permission to Sygna Bridge's callback url, and Sygna Bridge will then relay the permission to the originator's callback url.

Authentication

We implement API Authentication with API key. All VASPs must attach a valid api_key to every API call.

Data Confidentiality and Integrity

ECIES Encryption

const sygnaBridgeUtil = require('sygna-bridge-util');
const sensitive_data = {
    "originator": {
        "name": "Antoine Griezmann",
        "date_of_birth":"1991-03-21"
    },
    "beneficiary":{
        "name": "Leo Messi"
    }
};
const recipient_pubKey = "04b1f14590a37c5c5fdcdc4f6d606eb383a79d5f6d72c210ec4fab47c2e9a59b4fd1149d8e8fa31ac1a04a9142cda2a479c642fb606eaac14c874fd7426e379f54"
const private_info = sygnaBridgeUtil.crypto.sygnaEncodePrivateObj(sensitive_data, recipient_pubKey);

// 04acf400bab2961d3e7b801ee562e582274b7a8bdc9737e6b72cfaa9dc21cfde0a0ccf0d7b3a061814e157b11eb7c4b986765a10b1d4b0b9e0dbd0376a16a16162a8b6e9ff0319aef48af93522c33a4692e6e3a903de2d925a4580d304804a7cb3c191a61e212fae387f66f737fe3f97b05d960878515bfe391076fff6f588429f016321b96374049b72d2f6bb127c5a4488f0caec32dae9bc4f6289fcc78bf280b26957cda6013be81009acc07fee246aff0ace7f7016d99f9289b4410990d505d738ef4e

// const decoded_priv_info = sygnaBridge.crypto.sygnaDecodePrivateObg(private_info, recipient_privKey);

We apply Elliptic Curve Integrated Encryption Scheme (ECIES) to encrypt all sensitive data between communication of VASPs.

This following diagram shows how ECIES works. ECC public/private key cryptography is used in conjunction with the Diffie-Hellman primitive to allow both sides to independently generate a shared secret key, for one-time use to encrypt data with a symmetric key algorithm.

Ecies sygna

We have provided a JavaScript library on NPM to handle ECIES encryption and decryption. You can take a look at the sample usage on the right or visit our Github for more information.

ECDSA Signature

const sygnaBridgeUtil = require('sygna-bridge-util');

// POST Txid Signature Example

const transfer_id = "325592beef10daf73790b19cf3c4050669b9bfe4b11c45de7c40cebd792a905e";
const txid = "1a0c9bef489a136f7e05671f7f7fada2b9d96ac9f44598e1bcaa4779ac564dcd";
const myPrivKey = "61019d9bfdaecefab4b35273fa06c4baaa9451996611ff7a2904c252213ce544"
const TxIdObj = sygnaBridgeUtil.crypto.signSendTxId(transfer_id, txid, myPrivKey);
console.log(TxIdObj.signature);

//37d2b7fc42d863ba126834945f4bee6d17b249cb8b3bb09ded4defc7aea439e3469c84a140e73ed78a0c7abee1a819c5db9d7c9413640fcca9d766eff633de20

We apply an ECDSA signature to ensure data integrity. All API calls must attach a signature signed by the requesting VASP's local private key, and every VASP can verify if the message received is valid by checking the signature and the corresponding public key.

The Digital Signature also provides message authentication (the receiver can verify the originator of the message) and non-repudiation (the sender cannot falsely claim that they have not signed the message).

Our signing algorithm uses secp256k1 Elliptic Curve with SHA256 Hash function. The details of the signing process can also be found on our Github.

With our library, we provide simple interfaces to deal with input parameters, help you convert them into JSON object strings and then go through the signing process. You will need to use different interfaces to get signatures of different API requests. These interfaces generally return a signed object, which has already inserted the signature for you, and will be ready to put into a request body.

Sygna Bridge API

API Flow


API Endpoint

{sygna-bridge production domain} = https://api.sygna.io/sb/
{sygna-bridge staging domain} = https://staging-api.sygna.io/sb/


Sygna Bridge API helps VASP to exchange required compliance informations and obtain a cryptographically signed compliance record (we call it permission) before broadcasting anything to the blockchain. The complete flow works as follows:

VASP Registration and Verification

In order to use our API, you will need to contact us to request an API key. After you successfully register as a verified VASP in the Sygna Bridge Ecosystem, we will publish your public key associate with a vasp_code for any other VASP to query.

Before you start a permission request, you will need to know the transaction beneficiary's corresponding VASP and the public key of that VASP.

Main Permission Request Flow

During the main process of Signa Bridge's Permission Request, the originator of a cryptocurrency transaction first starts a permissionRequest, and posts it to the Sygna Bridge central server. The server will relay the request to the beneficiary VASP and wait for the callback of the validation result.

Whenever the beneficiary finishes the request validation, they will post a permission back to Sygna Server. The server will store the data and relay the message to the originator VASP's server and complete the process.

flow

Submit Transaction ID

After the originator VASP has successfully received the permission and a signature from the beneficiary VASP, the originator VASP can proceed with the transaction and broadcast it to the blockchain. After the transaction has been confirmed by the network, the originator should submit the on-chain transaction ID to Sygna Bridge for future query.

GET VASP

const fetch = require('node-fetch')
const url = "https://staging-api.sygna.io/sb/api/v1/bridge/vasp"
let response = await fetch(url, { "api_key":"4973a45555f3200b34937b5ae27 c0da8653a584271fda1869262fc7edad8b88d" })
response = await response.json();

Sample response

{
    "signature": "3044022007d96bd01bcbcb11149a8871370617c840a74a09bb6b66da5681748b6a0b58f902203de2977c12609761d91cbcd769d8f6e7315d33bbe0c6220d5428d9c2d5c5a8ab",
    "vasp_data": [
        {
            "vasp_name": "Exchange1",
            "vasp_code": "VASPUSNY1",
            "vasp_pubkey": "048709ef46f46c7e89b58987b606dc54eda62f88424517667305d91b3e86b8847f1b44a9659831880a15885ec43a722f76c356ec0ee373a273a0a7900dcd077339"
        },
        {
            "vasp_name": "Exchange2",
            "vasp_code": "VASPUSNY2",
            "vasp_pubkey": "04b1f14590a37c5c5fdcdc4f6d606eb383a79d5f6d72c210ec4fab47c2e9a59b4fd1149d8e8fa31ac1a04a9142cda2a479c642fb606eaac14c874fd7426e379f54"
        }
    ]
}

Request information of one or more Virtual Assets Service Provider.

API Endpoint

GET ${sygna-bridge domain}/api/v1/bridge/vasp

Header Values

Parameter Value Description
api_key {apikey} replace {apikey} with 64 chars long API key got from Sygna Bridge.

GET Status

const transfer_id: "eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab"
const url = "https://staging-api.sygna.io/sb/api/v1/bridge/transaction/status?transfer_id="+transfer_id
const headers = {
    "api_key":"4973a45555f3200b34937b5ae27c0da8653a584271fda1869262fc7edad8b88d"
};

let response = await fetch(url, {
    method: 'GET',
    headers: headers
});
await response = await response.json();

Sample response

{
    "transfer_id": "eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab",
    "private_info" : "04f76bf0372c4d4679a172aaaf7fe4746cb83f2a2e5d6a5afcfe6bba72ad4c540d7940853f5fd1f4928c541c39efae81e9165598bad256fab77f6d5c4bd8d135b0553e61bbaeb6d573c71b23d656ed9e4ac37f40106ebd3aab8839c77409a3890b5f056d4e11aaf87c6d29580869ec5f81d20ecaad266ba69e234a2eb627d5c7b95957d82fd1b69172f6bce480f74d9f4ea7d4d38300669c25723e91c5bce83ec8f29aedd4",
    "transaction" : {
        "originator_vasp_code":"VASPUSNY1",
        "originator_addr":"3KvJ1uHPShhEAWyqsBEzhfXyeh1TXKAd7D",
        "beneficiary_vasp_code":"VASPUSNY2",
        "beneficiary_addr":"3AGUBzgKsZYNjEb3CvYzBS2wHYec4QBuCZ",
        "transaction_currency":"0x80000000",
        "amount": 0.269726
    },
    "transfer_id" : "eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab",
    "created_at" : "2019-07-25T09:13:12.557+0000",
    "permission_status" : "ACCEPTED",
    "transfer_to_sender_time" : "2019-07-25T09:14:04.706+0000",
    "txid" : "1a0c9bef489a136f7e05671f7f7fada2b9d96ac9f44598e1bcaa4779ac564dcd"
}

Get status of specific Permission Request.

API Endpoint

GET ${sygna-bridge domain}/api/v1/bridge/transaction/status

Header Values

Parameter Value Description
api_key {apikey} replace {apikey} with 64 chars long API key got from Sygna Bridge.

Request Parameter

Parameter Type Description
transfer_id string Unique transfer Id got from permissionRequest api call.

POST Permission Request

const params = {
  data: {
    private_info: "04857fecaef8ae2b6d1e6555e55c395dd75e507ecec62742f6ac830a0e87b7bbef4c1a15ea049bae9ca925a517863d634933d6fe3099aa72eb4633ee3796f348195932b3647b32841b3535cdea8ddea70a2741dcbf7a9fca3f4660a7d400842d8a9fc4b3667b1b2b3557e004de654c42521166b3056effa77c613670bb2d72286b3c800ff5ce8b8c2274e2b0901797dea36c39eb810b5d5f7709f37c16ed65f3f3d79e4177ac1ed2827073673a9c3d9467504f72b69e7fa6f55b6267f23aca248687435181",
    transaction:
    {
        originator_vasp_code: 'VASPUSNY1',
        originator_addr: '3KvJ1uHPShhEAWyqsBEzhfXyeh1TXKAd7D',
        beneficiary_vasp_code: 'VASPUSNY2',
        beneficiary_addr: '3AGUBzgKsZYNjEb3CvYzBS2wHYec4QBuCZ',
        transaction_currency: '0x80000000',
        amount: 0.1384
    },
    data_dt:'2019-07-29T06:29:00.123Z',
    signature:"7e440ed0a978d05863d9b5fd674f4dbba264a1ce5fed72cd9bb2bfb16b4deaba54152d2b61f59d0f1ebf7e16fd6f575260851e9f5a1496e8f0f0805faa2f277a",
  },
  callback: {
    callback_url:"https://originator.com/api/v1/originator/transaction/permission",
    signature:"86890ed0a978d05863d9b5fd674f4dbba264a1ce5fed72cd9bb2bfb16b4deaba54152d2b61f59d0f1ebf7e16fd6f575260851e9f5a1496e8f0f0805faa553322"
  };
};
const url = "https://staging-api.sygna.io/sb/api/v1/bridge/transaction/permission-request"
const headers = {
    "Content-Type":"application/json",
    "api_key":"4973a45555f3200b34937b5ae27c0da8653a584271fda1869262fc7edad8b88d"
};

let response = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(params),
    headers: headers
});
await response = await response.json();

Sample response

{
    "transfer_id":"eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab"
}

The first step of the permission request flow. Should be called by the originator VASP to inform Sygna Bridge about the creation of a compliant transaction.

tx flow

API Endpoint

POST ${sygna-bridge domain}/api/v1/bridge/transaction/permission-request

Header Values

Parameter Value Description
Content-Type application/json
api_key {apikey} replace {apikey} with 64 chars long API key got from Sygna Bridge.

Body Parameter

Parameter Type Description
data Permission Request Data
callback Callback The endpoint url for Sygna Bridge to post final permission.

POST Permission

const params = {
    transfer_id: "eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab",
    permission_status: "ACCEPTED",
    signature:"7e440ed0a978d05863d9b5fd674f4dbba264a1ce5fed72cd9bb2bfb16b4deaba54152d2b61f59d0f1ebf7e16fd6f575260851e9f5a1496e8f0f0805faa2f277a",
};
const url = "https://staging-api.sygna.io/sb/api/v1/bridge/transaction/permission"
const headers = {
    "Content-Type":"application/json",
    "api_key":"4973a45555f3200b34937b5ae27c0da8653a584271fda1869262fc7edad8b88d"
};

let response = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(params),
    headers: headers
});
await response = await response.json();

Sample Response

{
    "message":""
}

This request works as a response of Sygna Bridge's Permission Request. Whenever a beneficiary VASP finishes processing the request from Sygna Bridge, it must post a permission request back to Sygna Bridge server, containing the confirmation result.

Sb permit

API Endpoint

POST ${sygna bridge domain}/api/v1/bridge/transaction/permission

Header Values

Parameter Value Description
Content-Type application/json
api_key {apikey} replace {apikey} with 64 chars long API key got from Sygna Bridge.

Body Parameter

Parameter Type Description
transfer_id string
permission_status string "ACCEPTED" or "REJECTED"
signature string signature of object containing previous 2 fields.

POST Transaction ID

const params = {
    transfer_id: "eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab",
    txid:"1a0c9bef489a136f7e05671f7f7fada2b9d96ac9f44598e1bcaa4779ac564dcd",
    signature:"7e440ed0a978d05863d9b5fd674f4dbba264a1ce5fed72cd9bb2bfb16b4deaba54152d2b61f59d0f1ebf7e16fd6f575260851e9f5a1496e8f0f0805faa2f277a"
};
const url = "https://staging-api.sygna.io/sb/api/v1/bridge/transaction/txid"
const headers = {
    "Content-Type":"application/json",
    "api_key":"4973a45555f3200b34937b5ae27c0da8653a584271fda1869262fc7edad8b88d"
};

let response = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(params),
    headers: headers
});
await response = await response.json();

Sample response

{
    "message": ""
}

Submit broadcasted transaction ID on the blockchain for Sygna Bridge to keep as a record.

API Endpoint

POST ${sygna-bridge domain}/api/v1/bridge/transaction/txid

Header Values

Parameter Value Description
Content-Type application/json
api_key {apikey} replace {apikey} with 64 chars long API key got from Sygna Bridge.

Body Parameter

Parameter Type Description
transfer_id string Unique transfer Id got from permissionRequest api call.
txid string Corresponding hex transaction ID on the blockchain
signature string The signature of object containing 2 previous field.

VASP API

A Vasp must implement the following 2 endpoints to fully function with the Sygna Bridge ecosystem, acting as a beneficiary and an originator accordingly.

We have provided a sample NodeJS based API on Github so you can take a look at how the two endpoints should process or callback Sygna Bridge.

POST Permission Request (as Beneficiary)

Your beneficiary server should be able to response to following request.

const params = {
  data: {
    private_info: "04857fecaef8ae2b6d1e6555e55c395dd75e507ecec62742f6ac830a0e87b7bbef4c1a15ea049bae9ca925a517863d634933d6fe3099aa72eb4633ee3796f348195932b3647b32841b3535cdea8ddea70a2741dcbf7a9fca3f4660a7d400842d8a9fc4b3667b1b2b3557e004de654c42521166b3056effa77c613670bb2d72286b3c800ff5ce8b8c2274e2b0901797dea36c39eb810b5d5f7709f37c16ed65f3f3d79e4177ac1ed2827073673a9c3d9467504f72b69e7fa6f55b6267f23aca248687435181",
    transaction:
    {
        originator_vasp_code: 'VASPUSNY1',
        originator_addr: '3KvJ1uHPShhEAWyqsBEzhfXyeh1TXKAd7D',
        beneficiary_vasp_code: 'VASPUSNY2',
        beneficiary_addr: '3AGUBzgKsZYNjEb3CvYzBS2wHYec4QBuCZ',
        transaction_currency: '0x80000000',
        amount: 0.1384 
    },
    data_dt:'2019-07-29T06:29:00.123Z',
    signature:"7e440ed0a978d05863d9b5fd674f4dbba264a1ce5fed72cd9bb2bfb16b4deaba54152d2b61f59d0f1ebf7e16fd6f575260851e9f5a1496e8f0f0805faa2f277a",
  },
  transfer_id:"eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab"
};
const url = "https://beneficiary.example/api/v1/bridge/transaction/permission-request"
const headers = {
    "Content-Type":"application/json",
};

let response = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(params),
    headers: headers
});
await response = await response.json();

Sample Response

{
    "message":""
}

Bnf req

When the Sygna Bridge get a Permission Request, it will verify the request first to ensure the data integrity, and then Relay the request to corresponding beneficiary server.

API Endpoint

POST ${beneficiary domain}/api/v1/beneficiary/transaction/permission-request

Header Values

Parameter Value Description
Content-Type application/json

Body Parameter

Most of the body parameter

Parameter Type Description
data Permission Request Data Data from originator
transfer_id string

POST Permission (as Originator)

Your originator server should be able to response to following request.

const params = {
    transfer_id: "eeac79bb6ad673bfb4444b3bed1191c4b084270445becb7fdc2af7a80bb66aab",
    permission_status: "ACCEPTED",
    signature:"7e440ed0a978d05863d9b5fd674f4dbba264a1ce5fed72cd9bb2bfb16b4deaba54152d2b61f59d0f1ebf7e16fd6f575260851e9f5a1496e8f0f0805faa2f277a",
};
const url = "https://originator.example/api/v1/originator/transaction/permission"
const headers = {
    "Content-Type":"application/json",
};

let response = await fetch(url, {
    method: 'POST',
    body: JSON.stringify(params),
    headers: headers
});
await response = await response.json();

Org permit

Each VASP needs to implement a permission endpoint to get a notification from Sygna Bridge.

When an originator posts a permission request to Sygna Bridge, it needs to attach this url in callback_url.

API Endpoint

POST ${originator domain}/api/v1/originator/transaction/permission

Header Values

Parameter Value Description
Content-Type application/json
Parameter Type Description
transfer_id string Data from Beneficiary
permission_status string Data from Beneficiary
signature string Data from Beneficiary

Custom Objects

Permission Request Data

Sample Transansfer Data Object

{
  "private_info": "04857fecaef8ae2b6d1e6555e55c395dd75e507ecec62742f6ac830a0e87b7bbef4c1a15ea049bae9ca925a517863d634933d6fe3099aa72eb4633ee3796f348195932b3647b32841b3535cdea8ddea70a2741dcbf7a9fca3f4660a7d400842d8a9fc4b3667b1b2b3557e004de654c42521166b3056effa77c613670bb2d72286b3c800ff5ce8b8c2274e2b0901797dea36c39eb810b5d5f7709f37c16ed65f3f3d79e4177ac1ed2827073673a9c3d9467504f72b69e7fa6f55b6267f23aca248687435181",
  "transaction":
  {
    "originator_vasp_code":"VASPUSNY1",
    "originator_addr":"3KvJ1uHPShhEAWyqsBEzhfXyeh1TXKAd7D",
    "beneficiary_vasp_code":"VASPUSNY2",
    "beneficiary_addr":"3AGUBzgKsZYNjEb3CvYzBS2wHYec4QBuCZ",
    "transaction_currency":"0x80000000",
    "amount": 0.97384
  },
  "data_dt":"2019-07-29T06:29:00.123Z",
  "signature":"3044022007d96bd01bcbcb11149a8871370617c840a74a09bb6b66da5681748b6a0b58f902203de2977c12609761d91cbcd769d8f6e7315d33bbe0c6220d5428d9c2d5c5a8ab"
}
Key Type Description
private_info string ECIES encoded Private Information
transaction Transaction
data_dt string Timestamp in ISO format: yyyy-mm-ddThh:mm:ss[.mmm]+0000
signature string

Transaction

Sample Transaction Object

{
    "originator_vasp_code":"VASPUSNY1",
    "originator_addr":"3KvJ1uHPShhEAWyqsBEzhfXyeh1TXKAd7D",
    "beneficiary_vasp_code":"VASPUSNY2",
    "beneficiary_addr":"3AGUBzgKsZYNjEb3CvYzBS2wHYec4QBuCZ",
    "transaction_currency":"0x80000000",
    "amount": 0.97384
}

Key Type Description
originator_vasp_code string
originator_addr string
beneficiary_vasp_code string
beneficiary_addr string
transaction_currency string ID format specified in BIP-44
amount number

Callback

Sample Originator Callback Object

{
    "callback_url":"https://originator/api/v1/originator/transaction/permission",
    "signature":"376f567dc97ce1132181b962e082423ffc98c6379603aab2f645f30cae11e5483252333f2c383d6c190638f0f26e2476c7a2d6e17fa3c55521b04f00e4be05b4",
}
Key Type Description
callbck_url string
signature string

Private Information

Sample Private Information Object

{
    "originator": {
        "name": "David Beckham",
        "date_of_birth":"1975-05-02"
    },
    "beneficiary":{
        "name": "Antoine Griezmann"
    }
}

Private information is the object that is being encoded with ECIES.

Key Type Description
originator OriginatorInfo
beneficiary BeneficiaryInfo

OriginatorInfo

Key Type Description
name string Use native language characters for local transactions; use romanized names for international transactions
physical_address (optional) string Physical Address ( For originator from US VASP )
national_identity_number (optional) string National Identity Number
date_of_birth (optional) string Date of birth in ISO format
unique_identity (optional) string

BeneficiaryInfo

Key Type Description
name string Use native language characters for local transactions; use romanized names for international transactions

Errors

The API uses the following error codes:

HTTP Status Meaning
400 Bad Request -- Your request is malformed, invalid, or you are missing parameters
401 Unauthorized -- Please make sure authentication was done properly
403 Forbidden -- This API request requires additional access rights.
404 Not Found -- The specified entity could not be found.
500 The server encountered an unexpected condition which prevented it from fulfilling the request.