Zodia Custody API Documentation

Introduction

This document outlines the required steps to integrate with Zodia using our API.
Document created on April 20th, 2021. Last updated on November 8th, 2021.

API Documentation Zodia Platform version
1.3 1.10+

Please note that you can access the previous version of this document by using this link

Contact: customerservice@zodia.io

What's new ?

List of changes in the newest Zodia Platform APIs

  • Added new endpoints to:
  • The payload of Zodia Platform APIs are now documented with proper description and example. That includes:
    • Description of the fields in the request/response payload
    • Sample values in the request/response samples
  • The endpoints tagged [Diem Only] are now deprecated and will be removed in the next version
  • Added 2 new sections in the documentation:

Getting started

  • Zodia's API is RESTful over HTTPS and consumes JSON payload
  • Transport level security is TLS 1.2.
  • Requests must be digitally signed using SHA256withRSA (minimum 2048 bits)
  • Zodia's API requires at least two users: a maker (creation request) and a checker (approval request)
  • The examples below in Python require the libraries:
    • cryptography that can be installed with pip: pip install cryptography
    • requests that can be installed with pip: pip install requests

Company on-boarding for API interaction

Before invoking Zodia's API, your company's account must be set up onto Zodia by Zodia's staff.
To complete this setup, your company must generate a key pair. We will refer to these keys as:

  • company_pri_key for the private key
  • company_pub_key for the public key

Those keys must be RSA keys (encoded in base 64) with a minimum size of 2048 bits.
Once generated, your company must share the public key company_pub_key with Zodia's staff: customerservice@zodia.io

WARNING: You must never share the private key company_pri_key with anyone including Zodia staff. This private key must be stored securely

How to generate keys for a company

Below is an example of how to generate a key pair for the company named ZTEST:

import os
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

def generate_rsa_keypair(company):
    rsa_private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend())
    private_key_pem = rsa_private_key.private_bytes(serialization.Encoding.PEM,
                                                serialization.PrivateFormat.PKCS8,
                                                serialization.NoEncryption())
    with open(os.path.join("keys", company + ".private.pem"), "wb") as private_key_out:
        private_key_out.write(private_key_pem)

    rsa_public_key = rsa_private_key.public_key()
    public_key_pem = rsa_public_key.public_bytes(serialization.Encoding.PEM,
                                              serialization.PublicFormat.SubjectPublicKeyInfo)
    with open(os.path.join("keys", company + ".public.pem"), "wb") as public_key_out:
        public_key_out.write(public_key_pem)

if __name__ == '__main__':
    generate_rsa_keypair("ZTEST")
    # Private key "company_pri_key" can be found in the file "ZTEST.private.pem"
    # Public key "company_pub_key" can be found in the file "ZTEST.public.pem"

Company API users

At least two API users must be added to your company's account.

Important note

If the company has already been set up as explained above in the document, then Zodia customer service cannot create any API accounts on the created company. Only your company user maker will be able to create these two required API accounts.
However, if the company has not already been set up on Zodia UI, then Zodia onboarding team can create the company with the two required API accounts. Other user accounts can also be created by Zodia team at the time of the new company creation.

By convention, the API users should have an id starting with api-. Examples: api-maker and api-checker
To onboard these users, you must generate a key pair for each API user. We will refer to these keys as:

  • api_user_pri_key for the private key
  • api_user_pub_key for the public key

Each API user is composed of three pieces of information:

  • an api user email (just an identifier)
  • an Elliptic Curve public key (encoded in base 64)
  • an api user id which is the concatenation of the api user email with the first 10 letters of the hexadecimal representation of the hash (SHA256) of the public key.

These 3 pieces of information must then be shared with Zodia's staff: customerservice@zodia.io

Applying the two "How-to" steps below results in the following example:

  • api user email: api-maker@zodia.io
  • api user id: api-maker@zodia.io::76b728bb89
  • public key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeo/e0vtlHo44xeAOvDxZtlmnyKgkQrvoq/M2kpawqGOO+7FrUPktZm+wxqzE/Etta5F8sewpqYK5RgCbXtplSA==

WARNING: You must never share the private key api_user_pri_key with anyone including Zodia staff. This private key must be stored securely

How to generate keys for an API user

Please note that the Elliptic Curve that must be used to generate those keys is SECP256R1
Below is an example of how to generate a key pair for the user whose email is api-maker@zodia.io:

import os
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec

def generate_ec_keypair(user):
    ec_private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
    private_key_pem = ec_private_key.private_bytes(serialization.Encoding.PEM,
                                                serialization.PrivateFormat.PKCS8,
                                                serialization.NoEncryption())
    with open(os.path.join("keys", user + ".private.pem"), "wb") as private_key_out:
        private_key_out.write(private_key_pem)

    ec_public_key = ec_private_key.public_key()
    public_key_pem = ec_public_key.public_bytes(serialization.Encoding.PEM,
                                              serialization.PublicFormat.SubjectPublicKeyInfo)
    with open(os.path.join("keys", user + ".public.pem"), "wb") as public_key_out:
        public_key_out.write(public_key_pem)

if __name__ == "__main__":
    generate_ec_keypair("api-maker@zodia.io")
    # Private key "api_user_pri_key" can be found in the file "api-maker@zodia.io.private.pem"
    # Private key "api_user_pub_key" can be found in the file "api-maker@zodia.io.public.pem"

How to generate user id for an API user

Once you have the public key of the API user, you can generate the api user id by doing:

import os, binascii
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization

def generate_zodia_user_id(user):
    with open(os.path.join("keys", user + ".public.pem"), "rb") as public_key_in:
        ec_public_key = serialization.load_pem_public_key(public_key_in.read(), backend=default_backend())

    public_key_bytes = ec_public_key.public_bytes(serialization.Encoding.DER,
                                                  serialization.PublicFormat.SubjectPublicKeyInfo)
    digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
    digest.update(public_key_bytes)
    sha256 = digest.finalize()
    hex_id = binascii.hexlify(sha256).decode('UTF-8')
    return user + "::" + hex_id[-10:]

if __name__ == "__main__":
    zodia_user_id = generate_zodia_user_id("api-maker@zodia.io")
    print(zodia_user_id)  # api-maker@zodia.io::76b728bb89

Rate limiting

In order to provide a high-quality service, Zodia's API is rate limited. The default limits are:

  • 1 request per second per endpoint
  • 128 requests per day per endpoint

Please reach out to Zodia if you wish to adjust the rate limit for given endpoints.
If the rate limit is exceeded, the API will respond with the status code HTTP 429 Too Many Requests. Please refer to the section Error codes.

Authentication

Zodia's API authentication requires each request to be signed.
These requests must be signed using company_pri_key, the private key of your company.
All REST requests must contain the following headers:

  1. company-identifier is the identifier provided to you during the setup of your company on the Zodia Platform.
  2. request-identifier is an unique randomly generated identifier
  3. request-timestamp is the timestamp (milliseconds elapsed since the unix epoch) of when the request is submitted. Please note that the request should be submitted within 5 minutes
  4. signature is the message signature(using the SHA256withRSA algorithm). Please refer to the section Signing requests.

All request bodies should have content type application/json and be valid JSON.

Signing the payload (for POST requests)

Before submitting a payload containing the field userSignature, you will need to sign a part of the payload with api_user_pri_key, your private key as an API user.
The content that must be signed is the stringified value of the object named details. For more details about a stringified value, see json-stable-stringify

The signed payload must not include optional and empty fields

Example: assuming you want to create an outgoing transaction with bitcoins, you will have to submit the payload:

{
    "cmd": {
        "details": {
            "action": "Create",
            "consumerMetadata": "NADA",
            "description": "Demo BTC transaction",
            "domainId": "ZTEST",
            "feeRate": "1",
            "feeTypeId": "High",
            "recipients": [{"amount": "1000", "recipientId": "2NDZNwKNZaKT9YFqqXRTzP5cZjNqZ59zhcE", "recipientIdType": "ledger", "subtractFee": true}],
            "submitterId": "api-maker@zodia.io::76b728bb89",
            "transactionId": "TRO-API-ZTEST-9436",
            "walletId": "ZTEST-NOBENF-8P8XKKAO"
        },
        "userSignature": "{{user_signature}}"
    }
}

where {{user_signature}} is the value obtained by signing the stringified value of the object details. Below is an example of how to sign:

import os, base64, json
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec

def stringify_transaction_details():
    transaction_details = {
        "action": "Create",
        "consumerMetadata": "NADA",
        "description": "Demo BTC transaction",
        "domainId": "ZTEST",
        "feeRate": "1",
        "feeTypeId": "High",
        "recipients": [{"amount": "1000", "recipientId": "2NDZNwKNZaKT9YFqqXRTzP5cZjNqZ59zhcE", "recipientIdType": "ledger", "subtractFee": True}],
        "submitterId": "api-maker@zodia.io::76b728bb89",
        "transactionId": "TRO-API-ZTEST-9436",
        "walletId": "ZTEST-NOBENF-8P8XKKAO"
    }

    return json.dumps(transaction_details, sort_keys=True, separators=(',', ':'))

def sign_transaction_details(details, user):
    with open(os.path.join("keys", user + ".private.pem"), "rb") as private_key_in:
        ec_private_key = serialization.load_pem_private_key(private_key_in.read(),
                                                            password=None,
                                                            backend=default_backend())
        signed_payload = ec_private_key.sign(str.encode(details), ec.ECDSA(hashes.SHA256()))
    b64_signed_payload = base64.b64encode(signed_payload).decode('UTF-8')
    return b64_signed_payload

def create_transaction_payload(details, signature):
    payload = {
        "cmd": {
            "details": json.loads(details),
            "userSignature": signature
        }
    }
    return json.dumps(payload, sort_keys=True, separators=(',', ':'))

if __name__ == "__main__":
    stringified_details = stringify_transaction_details()
    user_signature = sign_transaction_details(stringified_details, "api-maker@zodia.io")
    transaction_payload = create_transaction_payload(stringified_details, user_signature)

    print(transaction_payload) # {"cmd":{"details":{"action":"Create","consumerMetadata":"NADA","description":"Demo BTC transaction","domainId":"ZTEST","feeRate":"1","feeTypeId":"High","recipients":[{"amount":"1000","recipientId":"2NDZNwKNZaKT9YFqqXRTzP5cZjNqZ59zhcE","recipientIdType":"ledger","subtractFee":true}],"submitterId":"api-maker@zodia.io::76b728bb89","transactionId":"TRO-API-ZTEST-9436","walletId":"ZTEST-NOBENF-8P8XKKAO"},"userSignature":"MEUCIETyGxJZyK8mgzNdfed8pZ+QBdl3ViMyKB/S6y8ej3XgAiEA4QxdfJdeXdyOM/kqJGCQvKq8MG83jsio0MfXvOK+JNk="}}

You will obtain the payload below (prettified for the documentation) that you can submit to Zodia, once you have signed the whole request:

{
    "cmd":{
        "details":{
            "action": "Create",
            "consumerMetadata": "NADA",
            "description": "Demo BTC transaction",
            "domainId": "ZTEST",
            "feeRate": "1",
            "feeTypeId": "High",
            "recipients": [{"amount":"1000", "recipientId":"2NDZNwKNZaKT9YFqqXRTzP5cZjNqZ59zhcE", "recipientIdType":"ledger", "subtractFee":true}],
            "submitterId": "api-maker@zodia.io::76b728bb89",
            "transactionId": "TRO-API-ZTEST-9436",
            "walletId": "ZTEST-NOBENF-8P8XKKAO"
        },
        "userSignature": "MEYCIQD20c+Twi151LAvtvwru40/y5JUGkLTaVIrD22RZSuExAIhAN6xDmO/psn/poTxywPL+NkOcC7DMNAFqleJeZ2Vy2Vv"
    }
}

Signing requests

Once the payload (for POST requests) is signed, you will need to sign the request that you send to Zodia.
Using : as separator, please concatenate the values of:

As an example for a GET request, the resulting string will be:
ZTEST:c730a02f-105d-4899-87aa-b1b8280e4a7e:1620141458133:https://dummy.server/api/core/wallets/ZTEST-NOBENF-8P8XKKAO/transactions/out?limit=25&from=2021-03-29:

The content of the header signature is generated by signing the string above with company_pri_key.
Example of code showing how to sign the request:

import os, base64, time, uuid, requests
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

def sign(data_to_sign, private_key):
    data_bytes = str.encode(data_to_sign)
    signature = private_key.sign(data_bytes, padding.PKCS1v15(), hashes.SHA256())
    return base64.b64encode(signature).decode('UTF-8')

def sign_for_zodia(company_identifier, url, payload):
    request_identifier = str(uuid.uuid4())
    request_timestamp = str(int(time.time() * 1000))
    data_to_sign = ":".join([company_identifier, request_identifier, request_timestamp, url, payload])
    print(data_to_sign)   # ZTEST:c730a02f-105d-4899-87aa-b1b8280e4a7e:1620141458133:https://dummy.server/api/core/wallets/ZTEST-NOBENF-8P8XKKAO/transactions/out?limit=25&from=2021-03-29:

    with open(os.path.join("keys", company_identifier + ".private.pem"), "rb") as private_key_in:
        rsa_private_key = serialization.load_pem_private_key(private_key_in.read(),
                                                             password=None,
                                                             backend=default_backend())

        signature = sign(data_to_sign, rsa_private_key)
    return company_identifier, request_identifier, request_timestamp, signature

if __name__ == "__main__":
    full_url = "https://dummy.server/api/core/wallets/ZTEST-NOBENF-8P8XKKAO/transactions/out?limit=25&from=2021-03-29"
    headers = sign_for_zodia("ZTEST", full_url, "")

    response = requests.get(full_url, headers={
        "company-identifier": headers[0],         # ZTEST
        "request-identifier": headers[1],         # c730a02f-105d-4899-87aa-b1b8280e4a7e
        "request-timestamp": headers[2],          # 1620141458133
        "signature": headers[3]                   # aZBZNDeDJomgRBZFhV24MbdlyfSiqJuCMgz5mSl+dpxtDDgbadTuin0z920eBD2YFP5g3ccakguQUXPMuLp4Umyet3hGYXb2GiMkKSIA8XocdF8uG2xReSZq+JSbuDSO7yQcxXVK10A6mL2f/zJuTFBRl20jegiHOBcbDlAOUkWS3Vam3KRLA/Nd8ZwOhK6XZbtZWGz0AW9obE7cpEwqUEposucx7J462XAaM9Duh+CF1ALhuo67G0hLYAtwqryRVhUdBvVrqoWgGu3quxfIYgG/8okYv2hHjzBtIfo2VREi4TlgsRXvGPQpSI534S8o9laa5Ddq1f6N2u1sXkE97g==
    })

Error codes

Zodia's API offers a number of error codes to facilitate your usage and troubleshooting.
Zodia uses HTTP response codes to indicate the success or failure of an API request. In general:

  • 200 indicate success
  • 4xx range indicate a failure given the information provided(e.g. a required parameter was omitted, etc...)
  • 500 indicate an error with Zodia's servers

In addition to these HTTP response codes, Zodia provides in the response payload:

  • an error code starting with ER- that should be shared with Zodia for troubleshooting
  • a human-readable message providing more details about the errors

The table below describes some errors you may encounter:

HTTP status code Error code Error message Description
400 ER-101 Missing mandatory field: field_name A mandatory field is missing in the payload received by Zodia
400 ER-102 Entity with id: entity_id does not exist You are trying to use an entity (company, wallet, transaction, etc…) that does not exist
400 ER-103 Size of the field: field_name must be between min_value and max_value Length of the value provided does not match the expected size
400 ER-104 Entity with id: entity_id already exists You are trying to create an entity (company, wallet, transaction, etc…) which already exists
400 ER-107 Field: field_name must not be blank
  • Field is missing
  • Value of the field is empty
400 ER-108 Field: field_name does not match the expected pattern: regexp_value You sent a value that does not match the pattern expected by Zodia
400 ER-111 Value of the field: field_name is not a supported cryptocurrency The cryptocurrency provided is not currently supported by Zodia
400 ER-112 Field: field_name must not be empty You sent an empty value/list while Zodia is expecting at least one value
400 ER-113 Entity with id: entity_id is deactivated You are trying to use a deactivated entity
400 ER-114 Field: field_name does not match with user's company The value you provided for the field (usually "domainId") does not match your company's identifier
400 ER-115 Field: field_name does not match with resource parameter: path_parameter The value you provided in the payload does not match the path parameter used in the resource
400 ER-116 Value of the field: field_name must contain only digits You sent a value that is not a numeric value
400 ER-117 Value of the field: field_name must be equal to value You must send a value strictly equal to the value expected by Zodia
400 ER-121 Field: field_name must be greater than or equal to value You must send a value greater than or equal to the value expected by Zodia
400 ER-122 Field: field_name must be less than or equal to value You must send a value lesser than or equal to the value expected by Zodia
400 ER-124 Only max_value minutes of drift are allowed Zodia allows 5 minute of drift between the signed timestamp provided and the instant that Zodia receives the query
400 ER-202 Header: header must not be blank
  • Header is missing
  • Value of the header is empty
405 ER-204 Available methods : available_methods You must choose from the available methods for an endpoint. Example: GET,POST
429 ER-208 Rate limit exceeded. Try again later You exceeded the number of queries per second defined by Zodia
Please refer to the section Rate limiting
429 ER-209 Daily quota exhausted. Try again later You exhausted the number of queries per day defined by Zodia
Please refer to the section Rate limiting
401 ER-210 Signature verification failed Zodia was not able to verify the signature you provided. Either because:
  • private key that signed the data does not match with public key shared with Zodia
  • Data signed is wrong

Please refer to the section Authentication
401 ER-211 Access to this resource is denied The entitlements defined by Zodia don’t allow you to access this resource
400 ER-502 Mismatch between transaction's wallet currency and field: field_name The cryptocurrency you provided for the field is not consistent with the wallet used for the transaction
400 ER-503 Value of the field: field_name is not adapted to this endpoint You provided a value that is not supported by the endpoint you used. Example: "preburn" while using the endpoint "/api/core/transactions"
400 ER-504 Mismatch between field: field1_name and field: field2_name The fields "field1" and "field2" must have the same value
400 ER-505 Mismatch between transaction's wallet and field: field_name The value you provided for the field does not match the wallet used for the transaction
400 ER-506 Mismatch between transaction's company and field: field_name The value you provided does not match the company used for the transaction
400 ER-601 Ledger wallet is not compatible with this operation You are trying to initiate a contract-related transaction while using a wallet that does not support this operation
400 ER-604 Error retrieving the wallet address Zodia was not able to retrieve the address associated to this wallet
500 ER-1 Unexpected error: error Zodia encountered an unexpected error and can not fulfill the request
Please contact Zodia with the error's identifier beginning with the keyword "ERR"

Unit reference

The units used in the API are the smallest denomination for a currency per the reference table below:

Currency Unit
BTC Satoshi
ETH WEI

Status reference

The API will return status codes for some calls relating to wallets and transactions. These status codes can be mapped to human-readable messages using the following reference tables:

Wallet status

API Status Definition
ACTIVE Wallet currently active - Funds available
DEACTIVATED Wallet not active - Funds are not available
ZODIA_MAKER_APPROVED New client request submitted and validated
ZODIA_MAKER_REJECTED Rejected by client, wallet not created
ZODIA_MAKER_APPROVE_TIMEOUT New client request submitted but not approved within the expiry time
ZODIA_CHECKER_APPROVE_TIMEOUT Client approval not completed within the expiry time
SILO_OP_APPROVAL_REQUIRED Client and Zodia approvals pending
SILO_OP_PARTIAL_APPROVED Client approval is pending / Client approval is completed but Zodia approval is pending
SILO_OP_FULLY_APPROVED Client and Zodia approvals completed
SILO_OP_COMPLETED Client request completed, wallet created
SILO_OP_REJECTED Rejected by client / Rejected by Zodia
SILO_OP_FAILED Wallet creation failed, not completed
SILO_POST_ISSUE Wallet creation failed, not completed
SILO_OP_EXPIRED Approvals not completed within the expiry time
ZODIA_DRAFT Wallet can still be edited before submitted
ZODIA_DELETED Wallet deleted before submitted

Outgoing transaction status

API Status Definition
ZODIA_MAKER_APPROVED New client request submitted and validated
ZODIA_MAKER_REJECTED Rejected by client, outgoing transaction not created
ZODIA_MAKER_APPROVE_TIMEOUT New client request submitted but not approved within the expiry time
ZODIA_CHECKER_APPROVE_TIMEOUT Client approval not completed within the expiry time
SILO_OP_APPROVAL_REQUIRED Client and Zodia approvals pending
SILO_OP_PARTIAL_APPROVED Client approval is pending / Client approval is completed but Zodia approval is pending
SILO_OP_FULLY_APPROVED Client and Zodia approvals completed
SILO_OP_COMPLETED Client request completed, outgoing transaction created
SILO_OP_REJECTED Rejected by client / Rejected by Zodia
SILO_OP_FAILED Outgoing transaction failed, not completed
SILO_POST_ISSUE Outgoing transaction failed, not completed
SILO_TX_OUT_CONFIRMED Outgoing transaction confirmed after x blocks
SILO_OP_EXPIRED Approvals not completed within the expiry time
SILO_TX_OUT_FAILED Outgoing transaction failed, not completed
SILO_TX_OUT_SCHEDULED_FAILED Outgoing transaction failed, not completed
SILO_TX_OUT_SCHEDULED Outgoing transaction waiting to be processed
SILO_TX_OUT_PROCESSED Outgoing transaction broadcasted on-chain
ZODIA_UNDER_INVESTIGATION Outgoing transaction under investigation by Zodia

Incoming transaction status

API Status Definition
SILO_TX_IN_DETECTED Incoming transaction detected on-chain
SILO_OP_APPROVAL_REQUIRED Zodia approvals pending
SILO_OP_PARTIAL_APPROVED Zodia approvals pending
SILO_OP_ACTION_FULLY_APPROVED Zodia approvals completed
SILO_TX_IN_UNLOCKED Incoming transaction is unlocked - Funds available
SILO_TX_IN_CONFIRMED Incoming transaction confirmed after x blocks
SILO_OP_REJECTED Rejected by Zodia
SILO_OP_EXPIRED Approvals not completed within the expiry time
ZODIA_UNDER_INVESTIGATION Incoming transaction under investigation by Zodia

Network Fees

Get the estimated fee rate by currency

path Parameters
currency
required
string
Enum: "BTC" "ETH"

Currency

Responses

Response samples

Content type
application/json
{
  • "ledgerId": "BTC",
  • "ledgerAmount": "1"
}

Wallets

Return all wallets

Responses

Response samples

Content type
application/json
{
  • "wallets": [
    ]
}

Create new wallet

Request Body schema: application/json
name
required
string [ 1 .. 128 ] characters ^[a-zA-Z0-9 -]+$

Display name of the wallet

currency
required
string
Enum: "BTC" "ETH"

Currency of the wallet

beneficiaryId
string [ 1 .. 32 ] characters

ID of the beneficiary of the wallet

required
object

Signed payload proving you are the issuer of the command

Responses

Request samples

Content type
application/json
{
  • "name": "Demo wallet",
  • "currency": "BTC",
  • "beneficiaryId": "BNF-ZTEST-0DFUSJPF7A",
  • "cmd": {
    }
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Return a single wallet by ID

path Parameters
walletId
required
string

ID of the wallet

Responses

Response samples

Content type
application/json
{
  • "walletId": "ZTEST-NOBENF-849P8XKKAO",
  • "walletName": "Demo wallet",
  • "walletCompany": "ZTEST",
  • "walletCurrency": "BTC",
  • "unitBalances": {
    },
  • "balances": {
    },
  • "createdBy": "api-maker@zodia.io",
  • "createdAt": "2021-05-11 04:43:43.344",
  • "updatedAt": "2021-10-22 13:08:21.488",
  • "status": "ACTIVE",
  • "valid": true,
  • "registeredComplianceKey": true
}

Approve/reject new wallet

path Parameters
walletId
required
string

ID of the wallet

Request Body schema: application/json
required
object

Signed payload proving you are the issuer of the command

Responses

Request samples

Content type
application/json
{
  • "cmd": {
    }
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Get incoming transactions by wallet ID

path Parameters
walletId
required
string

ID of the wallet

query Parameters
limit
integer [ 1 .. 1024 ]
Default: 10

Number of results per request

from
string
Examples:
  • from=2021-03-29 - ISO-8601 date
  • from=2021-03-29T11:34:53Z - ISO-8601 date/time in UTC

Start and inclusive date/time of the query

to
string
Examples:
  • to=2021-03-29 - ISO-8601 date
  • to=2021-03-29T11:34:53Z - ISO-8601 date/time in UTC

End and inclusive date/time of the query

Responses

Response samples

Content type
application/json
{
  • "transfers": [
    ]
}

Get outgoing transactions by wallet ID

path Parameters
walletId
required
string

ID of the wallet

query Parameters
limit
integer [ 1 .. 1024 ]
Default: 10

Number of results per request

from
string
Examples:
  • from=2021-03-29 - ISO-8601 date
  • from=2021-03-29T11:34:53Z - ISO-8601 date/time in UTC

Start and inclusive date/time of the query

to
string
Examples:
  • to=2021-03-29 - ISO-8601 date
  • to=2021-03-29T11:34:53Z - ISO-8601 date/time in UTC

End and inclusive date/time of the query

Responses

Response samples

Content type
application/json
{
  • "transfers": [
    ]
}

Register compliance key [Diem only] Deprecated

path Parameters
walletId
required
string
Request Body schema: application/json
submitterId
required
string
transactionId
required
string [ 1 .. 40 ] characters TRX-COMPLIANCE-API-<companyId>-*

Responses

Request samples

Content type
application/json
{
  • "submitterId": "string",
  • "transactionId": "string"
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Approve/reject compliance key registration [Diem only] Deprecated

path Parameters
walletId
required
string
Request Body schema: application/json
required
object

Signed payload proving you are the issuer of the command

Responses

Request samples

Content type
application/json
{
  • "cmd": {
    }
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Get compliance key registration status [Diem only] Deprecated

path Parameters
walletId
required
string
transactionId
required
string

Responses

Response samples

Content type
application/json
{
  • "transactionId": "string",
  • "status": "string",
  • "rejectedReason": "string",
  • "complianceKey": "string",
  • "wallet": {
    }
}

Transactions

Create new outgoing transaction

Request Body schema: application/json
required
object

Signed payload proving you are the issuer of the command

object
Deprecated

Read-only field

Responses

Request samples

Content type
application/json
{
  • "cmd": {
    },
  • "complianceDetails": {
    }
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Get an outgoing transaction by ID

path Parameters
transactionId
required
string

ID of the transaction

Responses

Response samples

Content type
application/json
{
  • "companyId": "ZTEST",
  • "fromWallet": "ZTEST-NOBENF-849P8XKKAO",
  • "toAddress": "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt",
  • "consumerMetadata": "metadata",
  • "transferId": "TRO-API-ZTEST-4001",
  • "transferStatus": "ZODIA_MAKER_APPROVED",
  • "currency": "BTC",
  • "amountLedger": 641400,
  • "feeType": "HIGH",
  • "feeAmountLedger": 165,
  • "ledgerRef": "fd1c22fd097501606fddbc7d22e5009d45e9e6cb7115ad109a46f8319a385bd4",
  • "createdBy": "api-maker@zodia.io",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "complianceDetails": {
    }
}

Get an incoming transaction by ID

path Parameters
transactionId
required
string

ID of the transaction

Responses

Response samples

Content type
application/json
{
  • "companyId": "ZTEST",
  • "fromAddress": [
    ],
  • "toWallet": "ZTEST-NOBENF-849P8XKKAO",
  • "toAddress": "2Mz5ZH9e6Q53QfK2E1Azaos3Vq62niibhc1",
  • "transferId": "TRI-ZTEST-63Q4DZ0KJP",
  • "transferStatus": "SILO_TX_IN_DETECTED",
  • "currency": "BTC",
  • "amountLedger": 641400,
  • "ledgerRef": "2f6e77f8c4313d0925f71acf19a659398115bdf903e3af06b3b1776e756c096f",
  • "actionId": "TX_IN_ACTION-ZTEST-7LE2JCPZ3D",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "method": "TRANSFER"
}

Approve/reject new outgoing transaction

path Parameters
transactionId
required
string

ID of the transaction

Request Body schema: application/json
required
object

Signed payload proving you are the issuer of the command

Responses

Request samples

Content type
application/json
{
  • "cmd": {
    }
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Return transaction statistics

query Parameters
from
string
Examples:
  • from=2021-03-29 - ISO-8601 date
  • from=2021-03-29T11:34:53Z - ISO-8601 date/time in UTC

Start and inclusive date/time of the query

to
string
Examples:
  • to=2021-03-29 - ISO-8601 date
  • to=2021-03-29T11:34:53Z - ISO-8601 date/time in UTC

End and inclusive date/time of the query

Responses

Response samples

Content type
application/json
{
  • "from": "2019-08-24T14:15:22Z",
  • "to": "2019-08-24T14:15:22Z",
  • "transferOutStats": {
    },
  • "transferInStats": {
    }
}

Create a transaction draft [Diem only] Deprecated

Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "cmd": {
    }
}

Response samples

Content type
application/json
{
  • "empty": true,
  • "property1": { },
  • "property2": { }
}

Get the details of a transaction draft [Diem only] Deprecated

path Parameters
transactionId
required
string

Responses

Response samples

Content type
application/json
{
  • "status": "APPROVED",
  • "message": "string",
  • "cmd": {
    }
}

Preburn

Create a pre-burn transaction [Diem only] Deprecated

Request Body schema: application/json
required
object

Signed payload proving you are the issuer of the command

Responses

Request samples

Content type
application/json
{
  • "cmd": {
    }
}

Response samples

Content type
application/json
{
  • "requestId": "1f9c2b63-1d4b-4add-ba3a-18c8e8533f87"
}

Get a pre-burn transaction by ID [Diem only] Deprecated

path Parameters
transactionId
required
string

Responses

Response samples

Content type
application/json
{
  • "companyId": "ZTEST",
  • "fromWallet": "ZTEST-NOBENF-849P8XKKAO",
  • "toAddress": "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt",
  • "consumerMetadata": "metadata",
  • "transferId": "TRO-API-ZTEST-4001",
  • "transferStatus": "ZODIA_MAKER_APPROVED",
  • "currency": "BTC",
  • "amountLedger": 641400,
  • "feeType": "HIGH",
  • "feeAmountLedger": 165,
  • "ledgerRef": "fd1c22fd097501606fddbc7d22e5009d45e9e6cb7115ad109a46f8319a385bd4",
  • "createdBy": "api-maker@zodia.io",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "complianceDetails": {
    }
}

Miscellaneous

Ping GET

Responses

Response samples

Content type
application/json
{
  • "id": "ZODIA",
  • "from": "ZTEST",
  • "date": "2019-08-24T14:15:22Z",
  • "timeUTC": 1620708223000
}