Web API
Overview
# Please note that many of the Python examples presented use type
# annotations introduced in Python 3.6. They are easy to remove
# manually if you are using an older version of Python. You could
# also use the strip-hints library to remove the type hints from
# the code. Examples have been tested with CPython 3.6+ only.
The information below should be used to help you consume our Web API.
URLs
- Production URL: https://api.zerohash.com
- Certification URL: https://api.cert.zerohash.com
OpenAPI
- OpenAPI documentation: https://api.cert.zerohash.com/api-docs
Public Endpoints
Public endpoints do not require authentication. This information is fundamental to the exchange and publicly available.
Time
GET /time
const axios = require('axios')
axios.get('https://api.zerohash.com/time')
import requests
requests.get('https://api.zerohash.com/time')
Sample Response
{
"epoch": 1550174574
}
Return the current unix time of the server in seconds.
Authentication
const crypto = require('crypto')
const request = require('request-promise')
const makeRequest = (
apiKey,
apiSecret,
passphrase,
host,
route,
method,
body
) => {
// CREATE SIGNATURE
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + method + route + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
// Don't forget to base 64 encode your digest
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': apiKey,
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': passphrase
}
const derivedMethod = {
POST: 'post',
PUT: 'put',
GET: 'get'
}[method]
const options = {
headers,
body,
json: true
}
return request[derivedMethod](`https://${host}${route}`, options)
}
import hashlib
import hmac
import json
from base64 import b64decode, b64encode
from datetime import datetime
from typing import Any, Dict, Optional
from urllib.parse import urljoin
import requests
from logging import getLogger
# ℹ️ PLEASE NOTE: make sure you're pointing to the right environment:
# cert: https://api.cert.zerohash.com
# production: https://api.zerohash.com
BASE_URL = 'https://api.cert.zerohash.com'
# ℹ️ PLEASE NOTE: you should refer to the following article for instructions
# on how to create your API keys:
#
# https://zerohash.zendesk.com/hc/en-us/articles/1500009663981-Creating-API-Keys
#
# ⚠️ WARNING: **THESE CREDENTIALS SHOULD NEVER BE STORED IN PLAINTEXT**
# API keys here are kept in plaintext for the purposes of demonstration.
# We highly encourage you to store your keys encrypted and only decrypt them
# when being used.
#
API_PUBLIC_KEY = '<please fill me in>'
API_PRIVATE_KEY = '<please fill me in>'
PASSPHRASE = '<please fill me in>'
def sign_request(api_private_key: str, method: str,
resource_path: str, json_body: str, timestamp: str) -> bytes:
"""Signs a HTTP payload to be sent to Zero Hash API.
:param api_private_key: Key to sign the message with
:param method: HTTP method
:param resource_path: Relative path to the resource, e.g., /trades
:param json_body: JSON as a string. Usually created via json.dumps(dict)
:param timestamp: Unix Epoch time as a string
:return: Base64 encoded digest
"""
# ℹ️ PLEASE NOTE: the timestamp, HTTP method, resource path and JSON
# body used to generate the signature here must be signed exactly as send
# to the underlying HTTP request
msg = bytes(
timestamp + method + resource_path + json_body,
encoding='utf-8'
)
hm = hmac.new(
key=b64decode(api_private_key),
msg=msg,
digestmod=hashlib.sha256
)
return b64encode(hm.digest()).decode()
def build_headers() -> Dict[str, Any]:
"""Builds a template with the HTTP headers to be send in requests
to Zero Hash API.
"""
# ℹ️ PLEASE NOTE: datetime.timestamp is available only in Python 3.3+
# This is the Unix epoch.
timestamp = str(int(datetime.now().timestamp()))
return {
'X-SCX-API-KEY': API_PUBLIC_KEY,
'X-SCX-SIGNED': '<to be filled>', # PLEASE NOTE: will be auto filled below
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': PASSPHRASE
}
def send_signed_http_request(
method: str, resource_path: str, body: Optional[Dict[str, str]] = None
) -> requests.Response:
"""Builds and sends an HTTP request with a signature to the Zero Hash API.
:param method: HTTP method, such as GET, POST, PUT, PATCH, DELETE
:param resource_path: Relative path to the resource, e.g., /trades
:param body: Dictionary for serializing into the JSON body of the request.
For GET requests, this can be omitted or set to an empty dict.
Nothing will be sent, but it is required for the signature.
:return: requests.Response object
"""
if body is None:
body = {}
headers = build_headers()
json_body = json.dumps(body, separators=(',', ':'))
signature = sign_request(
API_PRIVATE_KEY,
method,
resource_path,
json_body,
headers['X-SCX-TIMESTAMP']
)
headers['X-SCX-SIGNED'] = signature
absolute_url = urljoin(BASE_URL, resource_path)
# ⚠️ WARNING: We are printing your signature headers to make it easier for
# troubleshooting in your local testing environment. For security reasons,
# please never do this on any real staging / production servers.
print('\n### REQUEST [{0}]\n'.format(absolute_url))
print('{0} {1}\n{2}'.format(method, resource_path, body))
print('X-SCX-API-KEY: {0}'.format(headers['X-SCX-API-KEY']))
print('X-SCX-TIMESTAMP: {0}'.format(headers['X-SCX-TIMESTAMP']))
print('X-SCX-PASSPHRASE: {0}'.format(headers['X-SCX-PASSPHRASE']))
print('X-SCX-SIGNED: {0}'.format(headers['X-SCX-SIGNED']))
request_args = {
'method': method,
'url': absolute_url,
'headers': headers
}
if body:
request_args['data'] = json_body
headers['Content-Type'] = 'application/json'
response = requests.request(**request_args)
# ℹ️ PLEASE NOTE: for production code you might want to consider a proper
# logging solution.
print('\n===> RESPONSE ###\n')
print(response.status_code)
print(response.text)
return response
if __name__ == '__main__':
# ⚠️ WARNING: We are printing your API keys here to make it easier for
# troubleshooting in your local testing environment. For security reasons,
# please never do this on any real staging / production servers.
print('\n### API KEYS ###\n')
print('API public key: {0}'.format(API_PUBLIC_KEY))
print('API private key: {0}'.format(API_PRIVATE_KEY))
print('Passphrase: {0}'.format(PASSPHRASE))
send_signed_http_request('GET', '/index?underlying=BTC"ed_currency=USD')
send_signed_http_request('GET', '/trades')
send_signed_http_request('GET', '/participants')
Example Headers
{
"X-SCX-API-KEY": "h2yFu1uijCDEqkbdop4GAF",
"X-SCX-SIGNED": "PFMlg+bMFVjjAiGPLR/zJCStmiiOIeyz5NIOZEmpfH0=",
"X-SCX-TIMESTAMP": 1550175822,
"X-SCX-PASSPHRASE": "passphrase"
}
Zero Hash Uses HMAC SHA-256 verification to ensure the authenticity of every API request.
To Authenticate with us, you will need to set the following headers:
Header | Description |
---|---|
X-SCX-API-KEY | Your public key |
X-SCX-SIGNED | Signature for your request |
X-SCX-TIMESTAMP | Unix timestamp |
X-SCX-PASSPHRASE | Your passphrase |
To sign your request:
- Concatenate timestamp + method + route + request body
Example: 1549468233POST/orders{"client_order_id":"abcdefg","instrument_code":"COSP:BTC/USD","market_code":"SCXM","order_type":"limit","price":"3780","quantity":"10","side":"buy"}
- Generate an HMAC digest using your private key (using HMAC SHA-256).
Example: Private Key = 2mC4ZvVd4goRkuJm+rjr9byUiaUW1b6tVN4xy9QXNSE=
- Encode the HMAC digest in Base64.
Using the above private key should produce a base64 encoded digest of: +p94Yo3z33zvTmoA+BFtzQIW+qJz1X8IZcnuudpX6A8=
Private Endpoints
# The below Python examples make use of the functions defined above.
Index
GET /index
Sample Response
{
"timestamp": 1564686909724,
"index": "BTC/USD",
"underlying": "BTC",
"quoted_currency": "USD",
"value": 1234.5678901234
}
Query for the most recently calculated Zero Hash Index value.
The following query parameters are required:
underlying
quoted_currency
Parameter | Description | Type |
---|---|---|
timestamp | When the index was calculated | timestamp |
index | The specific index, which is the unique combination of underlying and quoted_currency |
string |
underlying | The asset being valued | string |
quoted_currency | The asset in which the underlying is being valued |
string |
value | The index price for the underlying asset, as quoted in the quoted_currency |
number |
Assets
GET /assets
Sample Response
{
"message": [
{
"symbol": "SOL",
"name": "Solana",
"chain_code": "solana",
"type": "crypto",
"model": "account_based",
"withdrawal_minimum": "0.000001",
"stablecoin": false,
"precision": 9,
"tag_name": "none",
"fee_asset": "",
"rfq_liquidity_enabled": true,
"custody_enabled": true,
"deposit_address_creation": "none",
"deposits_onchain_confirms": 0,
"ny_allowed": false,
"contract_address": "NA"
},
{
"symbol": "USD",
"name": "US Dollar",
"chain_code": "",
"type": "fiat",
"model": "none",
"withdrawal_minimum": "0.01",
"stablecoin": false,
"precision": 2,
"tag_name": "none",
"fee_asset": "",
"rfq_liquidity_enabled": true,
"custody_enabled": true,
"deposit_address_creation": "none",
"deposits_on_chain_confirms": 0,
"ny_allowed": false,
"contract_address": "NA"
}
]
}
Query for all the assets supported by Zero Hash.
Optional query parameters include:
stablecoin
chain_code
symbol
ny_allowed
Parameter | Description | Type |
---|---|---|
stablecoin | Denotes whether the asset is considered a stablecoin | boolean |
chain_code | Identifies the protocol the asset is listed on | string |
symbol | Asset code used throughout the system | string |
ny_allowed | Shows if transactions for an asset are allowed in New York | boolean |
Trades
GET /trades
Sample Response
{
"message":[
{
"batch_trade_id":"None",
"trade_id":"5a37b3ce-adaf-4607-929d-863830b0c2f1",
"client_trade_id":"eac3abcd-f704-43ec-9e66-d3f00d19d76f",
"trade_state":"terminated",
"market_identifier_code":"",
"trade_reporter_code":"00SCXM",
"symbol":"USDC.ETH/USD",
"trade_quantity":"6.44",
"trade_price":"1",
"trade_type":"regular",
"physical_delivery":true,
"comment":"",
"last_update":1692907231719,
"transaction_timestamp":1692877183000,
"accepted_timestamp":1692877183724,
"defaulted_timestamp":"None",
"settled_timestamp":1692907231703,
"expiry_timestamp":"None",
"settlement_timestamp":"None",
"settlement_price_index_id":"None",
"contract_size":1,
"underlying":"USDC.ETH",
"quoted_currency":"USD",
"trade_reporter":"00SCXM",
"platform_code":"7SRK7O",
"product_type":"spot",
"parties_anonymous":false,
"bank_fee":"None",
"reporting_party":"00SCXM",
"settlement_schedule":"None",
"parties":[
{
"settling":false,
"participant_code":"00SCXM",
"side":"buy",
"asset":"USDC.ETH",
"amount":"null",
"liquidity_indicator":"None",
"execution_id":"",
"order_id":"",
"obligations_outstanding_timestamp":"None",
"current_obligations_met_timestamp":"None",
"settlement_state":"settled",
"client_order_id":"",
"collateral_percentage":"None",
"account_label":"general",
"account_profile":"None"
},
{
"settling":true,
"participant_code":"7SRK7O",
"side":"sell",
"asset":"USD",
"amount":"null",
"liquidity_indicator":"None",
"execution_id":"",
"order_id":"",
"obligations_outstanding_timestamp":"None",
"current_obligations_met_timestamp":"None",
"settlement_state":"None",
"client_order_id":"",
"collateral_percentage":"None",
"account_label":"general",
"account_profile":"None"
}
],
"session_id":"20230824000000",
"network_fee_notional":"None",
"network_fee_quantity":"None",
"total_notional":"6.44",
"asset_cost_notional":"6.44"
},
],
"page":1,
"total_pages":2,
"page_size":50
}
This returns an array of all trades received by Zero Hash where the requestor is the Platform, either party associated with the trade, or the account group where the trade was settled.
Optional query parameters include:
market_identifier_code
filters trades to ones on a specific market (SCXM for Seed Digital Commodities Market for example)omit_market_identifier_code
filters out trades from one specific marketplatform_code
filters trades to ones on a specific Platform on which the trade was executedomit_platform_code
filters out trades from one specific Platformtrade_state
filters trades to ones in a specific trade_statesettlement_state
filters trades to ones in a specific settlement_stateparty_code
filters trades to ones that include a party_code in any of the partiestransaction_timestamp
filters trades based on a given timestamp in milliseconds1593798130060
or nanoseconds1593798130060000000
using the following next params for the following filter types:[gt]
greater than a given timestamp, e.g.transaction_timestamp[gt]=1593798130060
[gte]
greater than or equal to a given timestamp, e.g.transaction_timestamp[gte]=1593798130060
[e]
equal to a given timestamp, e.g.transaction_timestamp[e]=1593798130060
[lt]
less than a given timestamp, e.g.transaction_timestamp[lt]=1593798130060
[lte]
lower than or equal to a given timestamp, e.g.transaction_timestamp[lte]=1593798130060
- combinations are also possible, e.g. to find a trades between
1593798130555
and1593798130777
you can use the next combinationtransaction_timestamp[gt]=1593798130555&transaction_timestamp[lt]=1593798130777
page
for paginating through the tradesclient_trade_id
filters trades based on the client_trade_idaccount_label
filters trades based on the account_labelreporting_party
filters trades based on the reporting_partysettlement_schedule
filters trades based on the settlement_schedule
GET /trades/:trade_id
A particular trade that has been submitted to Zero Hash for settlement. Note: the trade_id
field is the Zero Hash-provided identifier returned as a response to the trade submission endpoints.
Sample Response
{
"message": {
"trade_id": "9411a2d9-8964-47d0-8971-a52db2f65748",
"client_trade_id": "fjfd9wekdwoc0sdkcs09w",
"session_id": "20190801000000",
"trade_state": "terminated",
"market_identifier_code": "SCXM",
"reporting_party": "00SCXM",
"settlement_schedule": "ABCDEF",
"symbol": "BTC/USD",
"trade_quantity": "4",
"trade_price": "10000",
"trade_type": "block",
"physical_delivery": true,
"comment": null,
"last_update": 1565832456717,
"transaction_timestamp": 1565731066447,
"settlement_timestamp": 1565731965906,
"accepted_timestamp": 1565731066768,
"defaulted_timestamp": null,
"settled_timestamp": 1565794980952,
"contract_size": 1,
"bank_fee": "1.00",
"underlying": "BTC",
"quoted_currency": "USD",
"trade_reporter": "user@00SCXM.com",
"platform_code": "00SCXM",
"product_type": "spot",
"parties_anonymous": false,
"parties": [
{
"participant_code": "0M2CKW",
"side": "buy",
"asset": "BTC",
"amount": "4",
"liquidity_indicator": null,
"execution_id": "ex_id1",
"order_id": "foo",
"desk_code": null,
"trading_account_code": null,
"obligations_outstanding_timestamp": null,
"current_obligations_met_timestamp": null,
"settlement_state": "settled",
"client_order_id": null,
"settling": true,
"account_label": "general",
"commission": null,
"commission_asset": null,
"commission_payor_participant_code": null,
"commission_payor_account_group": null,
"commission_payor_account_label": null
},
{
"participant_code": "1J32WQ",
"side": "sell",
"asset": "USD",
"amount": "40000",
"liquidity_indicator": null,
"execution_id": "ex_id2",
"order_id": "foo",
"desk_code": null,
"trading_account_code": null,
"obligations_outstanding_timestamp": null,
"current_obligations_met_timestamp": null,
"settlement_state": "settled",
"client_order_id": null,
"settling": true,
"account_label": "general",
"commission": null,
"commission_asset": null,
"commission_payor_participant_code": null,
"commission_payor_account_group": null,
"commission_payor_account_label": null
}
],
"network_fee_notional": null,
"network_fee_quantity": null,
"total_notional": "0.02",
"asset_cost_notional": "0.02"
}
}
POST /trades
Sample Request
const postTrades = () => {
const body = {
symbol: "BTC/USD",
trade_reporter: "reporter@mail.com",
reporting_party: "AAAAAA",
settlement_schedule: "ABCDEF",
client_trade_id: "5155f7c9-95cb-4556-ab89-c178943a7111",
trade_price: "1",
trade_quantity: "0.0001",
platform_code: "AAAAAA",
parties_anonymous: false,
transaction_timestamp: 1670958435349,
product_type: "spot",
trade_type: "regular",
physical_delivery: true,
parties: [
{
participant_code: "BBBBBB",
asset: "BTC",
side: "buy",
settling: true
},
{
participant_code: "CCCCCC",
asset: "USD",
side: "sell",
settling: true
}
]
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/trades' + JSON.stringify(
body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
'https://api.zerohash.com/trades',
options
)
}
Sample Response
{
"message": {
"trade_id": "92616fce-31d3-465a-af01-0fb5d2dc4d40",
"client_trade_id": "f2f14251-e296-42ac-9bc7-01c9186b9219",
"session_id": "20190801000000",
"trade_state": "terminated",
"market_identifier_code": "TEST",
"trade_reporter": "reporter@mail.com",
"reporting_party": "SGC7CQ",
"settlement_schedule": "ABCDEF",
"symbol": "BTC/USD",
"trade_quantity": "1.0",
"trade_price": "10000.000000",
"trade_type": "regular",
"physical_delivery": true,
"comment": "Some comments about the trade for Zero Hash to store",
"settlement_timestamp": 1575849302321,
"transaction_timestamp": 1575849302321,
"accepted_timestamp": 1564686909724,
"settled_timestamp": null,
"defaulted_timestamp": null,
"contract_size": 1,
"bank_fee": "1.00",
"underlying": "BTC",
"quoted_currency": "USD",
"platform_code": "00TEST",
"product_type": "spot",
"parties_anonymous": true,
"last_update": 1564686909724,
"parties": [
{
"participant_code": "PKOHXY",
"side": "buy",
"asset": "BTC",
"amount": "1.0",
"liquidity_indicator": null,
"execution_id": null,
"order_id": null,
"current_obligations_met_timestamp": 1564686909724,
"obligations_outstanding_timestamp": 1564686909724,
"client_order_id": null,
"settling": true
},
{
"participant_code": "S1I5ED",
"side": "sell",
"asset": "USD",
"amount": "4000.0000",
"liquidity_indicator": null,
"execution_id": null,
"order_id": null,
"current_obligations_met_timestamp": 1564686909724,
"obligations_outstanding_timestamp": 1564686909724,
"client_order_id": null,
"settling": true
}
]
}
}
Allows a Trade Reporter to post executed spot trades to Zero Hash for settlement. The following fields are part of the submission.
Parameter | Description | Type |
---|---|---|
client_trade_id | A unique identifier for the trade, generally produced by the Platform on which the trade was executed Note: this must be unique, per platform, per 72 hour period |
string |
trade_reporter | A text field to indicate the name or identifier of the person or entity submitting the trade, e.g. an email address | string |
reporting_party (optional) | The original reporter of the trade. This field is optional and must be a 6 digit participant code of which you have proper relationships with | string |
settlement_schedule (optional) | Instructs Zero Hash to settle trades according to a certain schedule | string |
platform_code | The unique identifier to the Platform on which the trade was executed, as provided by Zero Hash | string |
market_identifier_code (optional) | The ISO 10383 market identifier code for the platform | string |
symbol | A free text field to identify the pair being traded, e.g. BTC/USD |
string |
product_type | spot or forward |
string |
trade_type | The type of trade to be settled Valid values are regular or block |
string |
trade_price | The price the trade was executed, refer to Note: If the amount is included per side, then this must equal to the seller's amount divided by the buyer's amount . Please use the calculation result with the full decimals, e.g. if the trade_price is calculated with 25 decimal places, please provide all 25 decimal places in your payload. |
string |
amount | Please make sure the 'amount' you pass follows Zero Hash's asset precision rules which can be found here - What assets do you support? If the amount does not follow the precision rules, only the amount value that falls within the allowed precision will be settled in the account at the end. |
|
trade_quantity (conditional) | The quantity purchased Note: if the amount is included per side, then this should not be included, otherwise it is required |
string |
physical_delivery | A boolean statement to indicate if the trade is physically delivered Currently Zero Hash only supports physically-settled trades, i.e. a value of true |
boolean |
transaction_timestamp | The unix timestamp the trade was executed on the external platform in milliseconds | timestamp |
comment (optional) | An optional field to use if there is any additional information needed | string |
parties_anonymous | A boolean flag to determine if the counterparties are known to each other Must be false if the platform_code is also a counterparty to the trade |
boolean |
parties[] | The counterparties of the trade Currently Zero Hash only supports 2 parties per trade |
array |
settlement_price_index_id (conditional) | The unique identifier of the benchmark settlement price to be used when calculating settlement obligations on trades that are settled at Zero Hash - required for forwards only |
string |
settlement_timestamp (optional) | The datetime when final settlement will first be attempted - if not included, the standard platform settlement instructions will be applied | number (unix ms timestamp) |
expiry_timestamp (optional) | The last datetime that the product can be traded, and the datetime that all final prices will be set, i.e. the fixing date - relevant for forwards onlyNote: after this point, there is no more ability to exit the trade or change its economics |
number (unix ms timestamp) |
bank_fee (optional) | An optional field that clients can use to specify the fee taken by the banking partner. This is used for reporting purposes only (supports 2 decimal places) | string |
network_fee_notional (optional) | The notional value of the network fee applied to the trade if applicable | string |
network_fee_quantity (optional) | The quantity of the network fee applied to the trade | string |
total_notional (optional) | The notional cost amount plus network fee notional amount | string |
asset_cost_notional (optional) | The cost of the asset in the notional amount | string |
Parameters for a specific party to a trade.
Parameter | Description | Type |
---|---|---|
side | The side of the party, buy or sell |
string |
participant_code | The participant code as assigned by Zero Hash Note: this will be Anonymous for counterparties to the trade if the parties_anonymous boolean was flagged as true by the Trade Reporter |
string |
asset | The asset that is being received by the party | string |
amount (conditional) | The amount of the asset that the party is receiving Note: if the trade_quantity is included, then this should not be included, otherwise it is required |
string |
liquidity_indicator (optional) | This an optional field that can be sent to mark whether the party added or removed liquidity upon execution, used for reporting purposes only |
string |
client_order_id (optional) | This is an optional field that may have been sent by your clients and can be sent as part of the request, used for reporting purposes only | string |
order_id (optional) | This is an optional field that can be used to identify orders within your system, used for reporting purposes only | string |
execution_id (optional) | This an optional field that can be used to identify the ID of the execution for orders, used for reporting purposes only | string |
settling | This field states which side(s) will be settled | string |
account_label (optional) | The account label allocated to the trade | string |
commission (optional) | Amount of the commission collected for the trade | string |
commission_asset (optional) | The asset type (e.g. USD, BTC) for the collected commission | string |
commission_payor_participant_code (optional) | The participant code tied to the commission | string |
commission_payor_account_group (optional) | The account group tied to the commission | string |
commission_payor_account_label (optional) | The account label tied to the commission | string |
As a response, all information provided in the trade submission will be returned, plus the following additional fields:
Parameter | Description | Type |
---|---|---|
trade_id | A unique ID from Zero Hash | string |
trade_state | accepted , active , terminated |
string |
accepted_timestamp | The timestamp when the trade was first accepted into Zero Hash with a trade_state of accepted |
timestamp |
current_obligations_met_timestamp | The most recent timestamp when the trade reached the settlement_state of current_obligations_met . Will be null if this has not occured yet |
timestamp |
obligations_outstanding_timestamp | The most recent timestamp when the trade reached the settlement_state of obligations_outstanding . Will be null if this has not occured yet |
timestamp |
settlement_state | null , obligations_oustanding , current_obligations_met , counterparty_defaulted , settled or defaulted |
string |
settled_timestamp | The timestamp when the trade fully settled all obligations, thereby reaching the terminal settlement_state of settled . Will be null if this has not occured yet |
timestamp |
defaulted_timestamp | The timestamp when the trade defaulted due to obligations not being met on time, thereby reaching the terminal settlement_state of defaulted . Will be null if this has not occured yet |
timestamp |
last_update | The timestamp that indicates the last time the trade was updated | timestamp |
session_id | This field reflects the Session Period - A discrete period in time encompassing all trading for a platform. This could be as short as one minute or as long as one business day. | string |
Trade Price
A trade_price
with any precision is accepted, however note that final settlement amounts are limited to the asset’s currency precision limit. Further, when calculating trade notional and settlement values, Zero Hash utilizes banker's rounding. See Precision column for more details.
Quantity and Amount
There are 2 methods of submitting trade price, quantity and amount information to Zero Hash. Depending on your setup, one may be more appropriate than the other:
- Submit
trade_price
andtrade_quantity
and we will therefore calculate the amount that each side will receive, e.g. for a BTC/USD trade, you may submit atrade_price
of 10,000 and atrade_quantity
of 1. We would therefore calculate that the buyer receives 1 BTC and the seller receives $10,000. This model is useful for trading platforms that have more defined instruments. - Submit
trade_price
and theamount
field per side, which means you explicitly state the amount that each side receives, e.g. for a BTC/USD trade, you may submit a trade_price of 10,000 and anamount
of 1 for the buy side anamount
of 10000 for the sell side. This is useful for platforms that have lots of flexibility in the amounts and assets that are traded. Note: if theamount
is included per side, then thetrade_price
must equal to the seller'samount
divided by the buyer'samount
, accurate for up to 20 figures.
Physical Delivery
This boolean determines if a product is physically or financially-settled.
true
means that the instrument is settled physically and the underlying is actually delivered to the buyer.false
means that the instrument is settled financially and there is a payment of differences between the buyer and seller according to some agreed-upon index.
Parties Anonymous
The parties_anonymous
field is used to protect counterparty information. In the event that a Trade Reporter wishes to keep the counterparty details anonymous, this flag can be set to true
. This is relevant for brokers and other types of agency execution providers.
Trade State
accepted
means the trade has been accepted by Zero Hash for settlement.active
means the trade is actively being settled.terminated
means the trade is in a terminal state, and has asettlement_state
of eithersettled
ordefaulted
.
Settlement State
null
means the trade hasn't been attempted to be settled yetobligations_outstanding
means the trade has been accepted by Zero Hash, and settlement has been attempted. However settlement could not be completed so the trade has been rolled to the next settlement session.current_obligations_met
means all obligations have been met for the trade but has yet to be settled by Zero Hashsettled
means the trade has fully settled.defaulted
means that the trade could not be settled by the expiry time, and so is deemed in default.counterparty_defaulted
means that the counterparty could not settle the trade by the expiry time.
POST /trades/batch
Sample Request
[
{
"symbol": "BTC/USD",
"trade_reporter": "reporter@mail.com",
"reporting_party": "AAAAAA",
"settlement_schedule": "ABCDEF",
"client_trade_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
"trade_price": "1",
"trade_quantity": "0.0001",
"platform_code": "AAAAAA",
"parties_anonymous": false,
"transaction_timestamp": 1602182786660,
"product_type": "spot",
"trade_type": "regular",
"physical_delivery": true,
"parties": [
{
"participant_code": "BBBBBB",
"asset": "BTC",
"side": "buy",
"settling": true
},
{
"participant_code": "CCCCCC",
"asset": "USD",
"side": "sell",
"settling": true
}
]
},
{
"symbol": "BTC/USD",
"trade_reporter": "reporter@mail.com",
"reporting_party": "DDDDDD",
"settlement_schedule": "ABCXYZ",
"client_trade_id": "5155f7c9-95cb-4556-ab89-c178943a7222",
"trade_price": "2",
"trade_quantity": "0.0002",
"platform_code": "DDDDDD",
"parties_anonymous": false,
"transaction_timestamp": 1602182786660,
"product_type": "spot",
"trade_type": "regular",
"physical_delivery": true,
"parties": [
{
"participant_code": "EEEEEE",
"asset": "BTC",
"side": "buy",
"settling": true
},
{
"participant_code": "FFFFFF",
"asset": "USD",
"side": "sell",
"settling": true
}
]
}
]
Sample Response
{
"message": [
{
"trade_id": "a51d841b-0b1f-441c-96e3-fd164e0b3ff8",
"client_trade_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
"session_id": "20190801000000",
"trade_state": "accepted",
"market_identifier_code": null,
"trade_reporter": "reporter@mail.com",
"reporting_party": "AAAAAA",
"settlement_schedule": "ABCDEF",
"symbol": "BTC/USD",
"trade_quantity": "0.0001",
"trade_price": "1",
"trade_type": "regular",
"physical_delivery": true,
"comment": null,
"last_update": 1602526124763,
"transaction_timestamp": 1602182786660,
"accepted_timestamp": 1602526124692,
"defaulted_timestamp": null,
"settled_timestamp": null,
"expiry_timestamp": null,
"settlement_timestamp": null,
"settlement_price_index_id": null,
"contract_size": 1,
"bank_fee": "1.00",
"underlying": "BTC",
"quoted_currency": "USD",
"trade_reporter": "AAAAAA",
"platform_code": "AAAAAA",
"product_type": "spot",
"parties_anonymous": false,
"parties": [
{
"participant_code": "BBBBBB",
"side": "buy",
"asset": "BTC",
"amount": "null",
"liquidity_indicator": null,
"execution_id": null,
"order_id": null,
"obligations_outstanding_timestamp": null,
"current_obligations_met_timestamp": null,
"settlement_state": null,
"client_order_id": null,
"collateral_percentage": null
},
{
"participant_code": "CCCCCC",
"side": "sell",
"asset": "USD",
"amount": "null",
"liquidity_indicator": null,
"execution_id": null,
"order_id": null,
"obligations_outstanding_timestamp": null,
"current_obligations_met_timestamp": null,
"settlement_state": null,
"client_order_id": null,
"collateral_percentage": null
}
],
"platform_name": null
},
{
"trade_id": "fe47ef4b-43d3-41c6-a7e9-42e414a6b34e",
"client_trade_id": "5155f7c9-95cb-4556-ab89-c178943a7222",
"session_id": "20190801000000",
"trade_state": "accepted",
"market_identifier_code": null,
"trade_reporter": "reporter@mail.com",
"reporting_party": "DDDDDD",
"settlement_schedule": "ABCXYZ",
"symbol": "BTC/USD",
"trade_quantity": "0.0002",
"trade_price": "2",
"trade_type": "regular",
"physical_delivery": true,
"comment": null,
"last_update": 1602526124648,
"transaction_timestamp": 1602182786660,
"accepted_timestamp": 1602526124637,
"defaulted_timestamp": null,
"settled_timestamp": null,
"expiry_timestamp": null,
"settlement_timestamp": null,
"settlement_price_index_id": null,
"contract_size": 1,
"bank_fee": "1.00",
"underlying": "BTC",
"quoted_currency": "USD",
"trade_reporter": "DDDDDD",
"platform_code": "DDDDDD",
"product_type": "spot",
"parties_anonymous": false,
"parties": [
{
"participant_code": "EEEEEE",
"side": "buy",
"asset": "BTC",
"amount": "null",
"liquidity_indicator": null,
"execution_id": null,
"order_id": null,
"obligations_outstanding_timestamp": null,
"current_obligations_met_timestamp": null,
"settlement_state": null,
"client_order_id": null,
"collateral_percentage": null
},
{
"participant_code": "FFFFFF",
"side": "sell",
"asset": "USD",
"amount": "null",
"liquidity_indicator": null,
"execution_id": null,
"order_id": null,
"obligations_outstanding_timestamp": null,
"current_obligations_met_timestamp": null,
"settlement_state": null,
"client_order_id": null,
"collateral_percentage": null
}
],
"platform_name": null
}
]
}
Allows a Trade Reporter to post multiple trades to Zero Hash for settlement. All trades submitted together must each independently pass validation for the batch to be accepted. If any trade is rejected, the entire batch will be rejected. This is useful for liquidity providers that wish to capture a spread between two counterparty trades.
The field requirements are the same as POST /trades, so please refer to the section above.
Positions
GET /positions
const getPositions = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/positions' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(`https://api.zerohash.com/positions`, options)
}
accounts = make_seed_request('GET', '/positions', {})
Sample Response
{
"message": [
{
"platform_code": "PLAT01",
"participant_code": "CUST01",
"asset": "BTC",
"position_all_open_trades": "10.02",
"position_all_accepted_trades_only": "10.02",
"position_all_active_trades_only": "0"
},
{
"platform_code": "PLAT01",
"participant_code": "CUST01",
"asset": "USD",
"position_all_open_trades": "-100200",
"position_all_accepted_trades_only": "-100200",
"position_all_active_trades_only": "0"
},
{
"platform_code": "PLAT02",
"participant_code": "CUST01",
"asset": "USDC",
"position_all_open_trades": "-110000",
"position_all_accepted_trades_only": "0",
"position_all_active_trades_only": "-110000"
},
{
"platform_code": "PLAT02",
"participant_code": "CUST01",
"asset": "USD",
"position_all_open_trades": "109670",
"position_accepted_trades_only": "0",
"position_active_trades_only": "109670"
}
]
}
Returns an array of all positions maintained at Zero Hash for the participant issuing the query. The response will include positions for all platforms for which the participant is active. Response parameters listed below.
Query parameters include:
platform_code
(optional) the platform_codes to filter the response by (e.g?platform_code=PLAT01&platform_code=PLAT02
)account_label
(optional) the account labels to filter the response by (e.g?account_label=general&account_label=PLAT02
)
Response:
Parameter | Description | Type |
---|---|---|
platform_code | The code of the platform for the position | string |
participant_code | The code of the participant that holds the position | string |
asset | The asset code for the for the position, e.g. USD |
string |
position_all_open_trades | The net position of all open trades in the asset, i.e. trades with a trade_state of accepted or active |
string |
position_accepted_trades_only | The net position of all trades in the asset with a trade_state of accepted , i.e. trades where settlement has not yet been attempted |
string |
position_active_trades_only | The net position of all trades in the asset with a trade_state of active , i.e. trades where settlement has been attempted but was unsuccessful |
string |
GET /positions/platform/:platform_code
const getPositionsForPlatform = (platformCode: string) => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/positions/' + platformCode + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/positions/platform/' + platformCode,
options
)
}
accounts = make_seed_request('GET', '/positions/platform/PLAT01', {})
Sample Response
{
"message": [
{
"platform_code": "PLAT01",
"participant_code": "CUST01",
"asset": "BTC",
"position_all_open_trades": "10.02",
"position_all_accepted_trades_only": "10.02",
"position_all_active_trades_only": "0"
},
{
"platform_code": "PLAT01",
"participant_code": "CUST01",
"asset": "USD",
"position_all_open_trades": "-100200",
"position_all_accepted_trades_only": "-100200",
"position_all_active_trades_only": "0"
},
{
"platform_code": "PLAT01",
"participant_code": "CUST02",
"asset": "USDC",
"position_all_open_trades": "-110000",
"position_all_accepted_trades_only": "0",
"position_all_active_trades_only": "-110000"
},
{
"platform_code": "PLAT01",
"participant_code": "CUST02",
"asset": "USD",
"position_all_open_trades": "109670",
"position_accepted_trades_only": "0",
"position_active_trades_only": "109670"
}
]
}
Returns an array of all positions maintained at Zero Hash for the platform issuing the query. The response will include positions for all participants active on the platform. Response parameters listed below.
Query parameters include:
participant_code
(optional) the participant_codes to filter the response by (e.g?participant_code=PLAT01&participant_code=PLAT02
)account_label
(optional) the account labels to filter the response by (e.g?account_label=general&account_label=PLAT02
)
Response:
Parameter | Description | Type |
---|---|---|
platform_code | The code of the platform for the position | string |
participant_code | The code of the participant that holds the position | string |
asset | The asset code for the for the position, e.g. USD |
string |
position_all_open_trades | The net position of all open trades in the asset, i.e. trades with a trade_state of accepted or active |
string |
position_accepted_trades_only | The net position of all trades in the asset with a trade_state of accepted , i.e. trades where settlement has not yet been attempted |
string |
position_active_trades_only | The net position of all trades in the asset with a trade_state of active , i.e. trades where settlement has been attempted but was unsuccessful |
string |
Accounts
GET /accounts
const getAccounts = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/accounts' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(`https://api.zerohash.com/accounts`, options)
}
accounts = make_seed_request('GET', '/accounts', {})
Sample Response
{
"message": [
{
"asset": "USD",
"account_owner": "ABCDEF",
"account_type": "collateral_deficiency",
"account_group": "XYZ456",
"account_label": "general",
"balance": "0.00",
"account_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3",
"last_update": 1554395972174
}
],
"page": 1,
"total_pages": 1
}
Query parameters include:
page
(optional) the page you would like to request (responses are paginated to 200 records per page)account_group
(optional) the account group to filter the response byaccount_label
(optional) the account label to filter the response byaccount_owner
(optional) the account owner value to filter the response byasset
(optional) the asset to filter the response byaccount_type
(optional) the account_type to filter the response by
Returns an array of all accounts with a non-zero balance maintained at Zero Hash and their balances as of the most recent settlement run. Response parameters listed below.
Parameter | Description | Type |
---|---|---|
asset | The asset code for the specific account, e.g. USD |
string |
account_owner | The code of the participant that owns the account | string |
account_type | available , collateral , payable , receivable or collateral_deficiency |
string |
account_group | The group that the account is a part of | string |
account_label | The account label associated with the account | string |
balance | The balance in the account | string |
account_id | Unique ID of the specific account | string |
last_update | Timestamp when the account balance was updated | timestamp |
Assets
Refer to our FAQ page to see which assets we support and their corresponding asset codes.
Account Type
Account types refer to their utilization. Zero Hash maintains 5 account types:
available
refers to assets that are free for use in trading, settling, for paying fees or withdrawingcollateral
refers to assets that are currently being held for open positions, if/when a trade has been collateralized by the platformpayable
refers to a settlement amount you must pay that is outstanding due having insufficientavailable
balance, or due to your counterparty having insufficientavailable
balancereceivable
refers to a settlement amount you will receive, but has not been paid due to you having insufficientavailable
balance to fulfill your side, or due to your counterparty having insufficientavailable
balance to fulfill theirscollateral_deficiency
refers to the amount that is owed by the participant to cover collateral requirements
Refer to our FAQ for more information: What types of accounts are supported?
Account Group
Account groups are utilized as part of the Zero Hash settlement infrastructure, to determine for which purpose the funds in the account have been allocated. Generally, an account group refers to a platform.
Refer to our FAQ for more information: What is an account group?
Account Label
Account Labels can be thought of as “sub account groups”. Within each account group, you can have many Account Labels. They are used to separate funds at a more granular level. The default value is general
.
Refer to our FAQ for more information: What is an Account Label?
GET /accounts/net_delivery_obligations
const getNDO = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/accounts/net_delivery_obligations' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
`https://api.zerohash.com/accounts/net_delivery_obligations`,
options
)
}
account = make_seed_request('GET', '/accounts/net_delivery_obligations', {})
Sample Response
{
"message": [
{
"asset": "USD",
"amount": "10532.15",
"account_group": "00SCXM",
"account_label": "general"
},
{
"asset": "BTC",
"amount": "3",
"account_group": "00SCXM",
"account_label": "general"
}
]
}
Your current net delivery obligations (NDO) across all accounts. See here for more information on NDOs: What does NDO mean?
Response parameters listed below.
Parameter | Description | Type |
---|---|---|
asset | The asset code for the specific account, e.g. USD |
string |
amount | The amount owed | string |
account_group | The sub account determination used for allocating towards settlements | string |
account_label | The account label associated with the account | string |
GET /accounts/:account_id
const getAccount = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/accounts/e5e18303-a352-4c28-8dab-3779e66a659b' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
`https://api.zerohash.com/accounts/e5e18303-a352-4c28-8dab-3779e66a659b`,
options
)
}
account = make_seed_request('GET', '/accounts/e5e18303-a352-4c28-8dab-3779e66a659b', {})
Sample Response
{
"message": {
"asset": "USD",
"account_owner": "ABC123",
"account_type": "collateral_deficiency",
"account_group": "00SCXM",
"account_label": "general",
"balance": "0.00",
"account_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3",
"last_update": 1554395972174
}
}
Information about a specific account. Response parameters listed below.
Parameter | Description | Type |
---|---|---|
asset | The asset code for the specific account, e.g. USD |
string |
account_owner | The code of the participant that owns the account | string |
account_type | available , collateral , payable , receivable or collateral_deficiency |
string |
account_group | The sub account determination used for allocating towards settlements | string |
balance | The balance in the account | string |
account_id | Unique ID of the specific account | string |
last_update | Timestamp of last settlement run | timestamp |
account_label | The account label associated with the account | string |
GET /accounts/:account_id/run_history
Sample Request
const getAccountRunHistory = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/accounts/e5e18303-a352-4c28-8dab-3779e66a659b/run_history' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
`https://api.zerohash.com/accounts/e5e18303-a352-4c28-8dab-3779e66a659b/run_history`,
options
)
}
Sample Response
{
"message": [
{
"run_timestamp": 1549577062214,
"run_type": "settlement",
"run_id": "500",
"change": "2000",
"new_balance": "146645"
},
{
"run_timestamp": 1520134020000,
"run_type": "deposit",
"run_id": "480",
"change": "100000",
"new_balance": "144645"
},
{
"run_timestamp": 1510101010000,
"run_type": "withdrawal",
"run_id": "375",
"change": "-20000",
"new_balance": "44645"
}
],
"page": 1,
"total_pages": 32
}
Returns the history of grouped settlements, deposits, withdrawals and other changes that have been applied to an account to lead up to its current balance.
Parameter | Description | Type |
---|---|---|
run_timestamp | The time that the particular run was executed | timestamp |
run_type | The type of run | string |
run_id | A unique ID for the particular run | string |
change | The net change to the account due to all movements within the particular run | string |
new_balance | The new account balance post-run | string |
Run Type
A run is a group of movements that pertain to the same type of change to an account. They are split into the following buckets:
Run | Description |
---|---|
deposit | deposit represents a new deposit into the particular account, always increasing the total balance of the account |
execution_fee | execution_fee represents a run to process fees incurred from trading on a Zero Hash liquidity venue |
network_fee | network_fee represents any and all blockchain network fees applied to an account, always decreasing the total balance of the account |
settlement | settlement is a group of movements due to margining and settling trades, which may increase or decrease the account balance |
transfer | transfer represents an internal transfer to or from an account at Zero Hash |
withdrawal | withdrawal represents an approved and processed withdrawal from a particular account, always decreasing the total balance of the account |
GET /accounts/:account_id/movements
Sample Request
const getAccountMovements = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/accounts/e5e18303-a352-4c28-8dab-3779e66a659b/movements' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
`https://api.zerohash.com/accounts/e5e18303-a352-4c28-8dab-3779e66a659b/movements`,
options
)
}
Sample Response
{
"message": [
{
"run_id": "500",
"movement_timestamp": 1554395972174,
"movement_id": "ab938734-0aa6-4378-baa1-2cc56aeee757",
"movement_type": "final_settlement",
"trade_id": "951806f4-d3ba-42c4-96fe-8083cd3202cf",
"deposit_reference_id": null,
"withdrawal_request_id": null,
"change": "100",
"parent_link_id": "f99411c3-5958-42f0-9ab7-d94d14221786"
},
{
"run_id": "500",
"movement_timestamp": 1554395972174,
"movement_id": "d8f902be-f8c3-4f9c-ac66-67000510900d",
"movement_type": "final_settlement",
"trade_id": "3ad29e08-8b4f-435b-89aa-17b7a298b350",
"deposit_reference_id": null,
"withdrawal_request_id": null,
"change": "-200",
"parent_link_id": "53fe5944-12ff-4d17-ac0f-34530b184f7a"
},
{
"run_id": "498",
"movement_timestamp": 1554395972000,
"movement_id": "c6af3d80-1aca-4280-b96b-a9b8d7ced46a",
"movement_type": "deposit",
"trade_id": null,
"deposit_reference_id": "ebedc42f-85c3-4468-8894-1cb6f49f7a04",
"withdrawal_request_id": null,
"change": "10000",
"parent_link_id": "27ebe256-fa77-4c27-b92e-111bc354be03"
},
{
"run_id": "497",
"movement_timestamp": 1554395972000,
"movement_id": "c6af3d80-1aca-4280-b96b-a9b8d7ced46a",
"movement_type": "withdrawal",
"trade_id": null,
"deposit_reference_id": null,
"withdrawal_request_id": "100",
"change": "-50",
"parent_link_id": "8de019e4-f1fa-40af-9296-1ccda8f02abe"
}
],
"page": 1,
"total_pages": 40
}
Returns the history of each itemized movement that has been applied to an account to lead up to its current balance.
Optional query parameters include:
page
for paginating through the movementsmovement_timestamp
filters movements based on a given timestamp in milliseconds1593798130060
or nanoseconds1593798130060000000
using the following next params for the following filter types:[gt]
greater than a given timestamp, e.g.movement_timestamp[gt]=1593798130060
[gte]
greater than or equal to a given timestamp, e.g.movement_timestamp[gte]=1593798130060
[e]
equal to a given timestamp, e.g.movement_timestamp[e]=1593798130060
[lt]
less than a given timestamp, e.g.movement_timestamp[lt]=1593798130060
[lte]
lower than or equal to a given timestamp, e.g.movement_timestamp[lte]=1593798130060
- combinations are also possible, e.g. to find a movements between
1593798130555
and1593798130777
you can use the next combinationmovement_timestamp[gt]=1593798130555&movement_timestamp[lt]=1593798130777
parent_link_id
filters movements that has the field parent_link_id equals to the parameter value
Parameter | Description | Type |
---|---|---|
run_id | A unique ID for the particular run | string |
movement_timestamp | The timestamp of the specific movement | timestamp |
movement_id | A unique ID for the specific account update | string |
movement_type | The type of movement | string |
trade_id | The unique identifier of the trade or loan that resulted in the movement, if the movement was due to a trade or loan If a trade, this is equal to the trade_id field provided via the /trades |
string |
deposit_reference_id | This is an external identifier associated with the deposit, if the movement was due to a deposit This is equal to the reference_id field provided via the /deposits endpoint |
string |
withdrawal_request_id | The withdrawal request ID, if the movement was due to a withdrawal This is equal to the id field provided via the /withdrawals/requests endpoint |
string |
change | The change due to the specific movement | string |
parent_link_id | The identifier of the transaction that originated the movement | string |
Movement Type
Movement | Description |
---|---|
collateralize_loan | A movement related to an increase in collateral held for any open loan(s) |
deposit | A deposit of additional assets into Zero Hash |
execution_fee | A movement due to incurred execution fees related to your trading activity on a Zero Hash liquidity venue |
final_settlement | A movement due to the full delivery and final settlement of a trade |
final_settlement_default | A movement due to a financially-settled trade whose final settlement obligation could not be fully settled due to a default |
final_settlement_default_fallback | A movement due to the financial settlement for the portion of a physically-settled trade's final settlement obligation that was not fully delivered due to a default |
final_settlement_default_partial | A movement due to the partial physical delivery of a physically-settled trade whose final settlement obligation could not be fully delivered due to a default |
initial_margin | A movement related to an increase or decrease in collateral held for any open position(s) |
interest_payment | A payment of interest for a loan |
loan_collateral_return | A movement related to a decrease in collateral held for any open loan(s) |
network_fee | A blockchain network fee incurred due to an on-chain movement related to your wallet |
principal_swap | A transfer of principal and collateral assets to open a loan |
repayment | A transfer to return principal and collateral for a loan that has terminated |
transfer | An internal transfer to or from an account at Zero Hash |
variation_margin | A payment made or collected due to changes in the market value of the position since the trade was executed or since the previous time the position was marked to market |
variation_margin_previous | A payment made or collected to settle a previously outstanding variation margin obligation |
withdrawal | A processed withdrawal from Zero Hash |
withdrawal_confirmed | Reversal of the temporary hold due to a withdrawal being processed |
withdrawal_pending | Temporary hold whilst a withdrawal is being processed |
POST /accounts/new
Sample Request
const postAccount = () => {
const body = {
participant_code: "PAR001",
prefunded: false,
account_label: "account-label"
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/accounts/new' + JSON.stringify(
body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
'https://api.zerohash.com/accounts/new',
options
)
}
accounts = make_seed_request('POST', '/accounts/new', {})
Sample Response
{
"message": {
"participant_code": "PAR001",
"account_group": "PLT001",
"account_label": "account-label",
"prefunded": false
}
}
Allows a platform to specify that an account is either pre-funded or not. NOTE: this is only relevant to our Central Limit Order Book (CLOB).
Parameter | Description | Type |
---|---|---|
participant_code | The code of the participant that owns the account | string |
account_label | the platform-dictated account label for the account. If not filled, the account label will be the participant_code. | string |
prefunded | indicates whether the participant has prefunded their account or not | boolean |
Movements
GET /movements
Sample Request
const getAccountMovements = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/movements?page=1&limit=3&account_id=e5e18303-a352-4c28-8dab-3779e66a659b' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
`https://api.zerohash.com/movements?page=1&limit=3&account_id=e5e18303-a352-4c28-8dab-3779e66a659b`,
options
)
}
Sample Response
{
"message": [
{
"movement_timestamp": 1554395972174,
"account_id": "e5e18303-a352-4c28-8dab-3779e66a659b",
"movement_id": "ab938734-0aa6-4378-baa1-2cc56aeee757",
"movement_type": "final_settlement",
"transfer_type": null,
"deposit_reference_id": null,
"withdrawal_request_id": null,
"parent_link_id": "f99411c3-5958-42f0-9ab7-d94d14221786",
"trade_id": "951806f4-d3ba-42c4-96fe-8083cd3202cf",
"change": "100"
},
{
"movement_timestamp": 1554395972174,
"account_id": "e5e18303-a352-4c28-8dab-3779e66a659b",
"movement_id": "d8f902be-f8c3-4f9c-ac66-67000510900d",
"movement_type": "final_settlement",
"transfer_type": null,
"deposit_reference_id": null,
"withdrawal_request_id": null,
"parent_link_id": "53fe5944-12ff-4d17-ac0f-34530b184f7a",
"trade_id": "3ad29e08-8b4f-435b-89aa-17b7a298b350",
"change": "-200"
},
{
"movement_timestamp": 1554395972000,
"account_id": "e5e18303-a352-4c28-8dab-3779e66a659b",
"movement_id": "c6af3d80-1aca-4280-b96b-a9b8d7ced46a",
"movement_type": "deposit",
"transfer_type": null,
"deposit_reference_id": "ebedc42f-85c3-4468-8894-1cb6f49f7a04",
"withdrawal_request_id": null,
"parent_link_id": "27ebe256-fa77-4c27-b92e-111bc354be03",
"trade_id": null,
"change": "10000"
}
],
"page": 1,
"total_pages": 10
}
Returns movements that lead up to current account balance.
Optional query parameters include:
page
for paginating through the movements. Defaults to 1.page_size
for limit the results per page. Defaults to 200.account_id
filters movements that has the field account_id equals to the parameter value.movement_type
filters movements that has the field movement_type equals to the parameter value.transfer_type
filters movements that has the field transfer_type equals to the parameter value.parent_link_id
filters movements that has the field parent_link_id equals to the parameter value.
Parameter | Description | Type |
---|---|---|
movement_timestamp | The timestamp of the specific movement | timestamp |
account_id | A unique ID for the specific account | timestamp |
movement_id | A unique ID for the specific account update | string |
movement_type | The type of movement | string |
transfer_type | The type of transfer | string |
trade_id | The unique identifier of the trade or loan that resulted in the movement, if the movement was due to a trade or loan If a trade, this is equal to the trade_id field provided via the /trades |
string |
deposit_reference_id | This is an external identifier associated with the deposit, if the movement was due to a deposit This is equal to the reference_id field provided via the /deposits endpoint |
string |
withdrawal_request_id | The withdrawal request ID, if the movement was due to a withdrawal This is equal to the id field provided via the /withdrawals/requests endpoint |
string |
change | The change due to the specific movement | string |
parent_link_id | The identifier of the transaction that originated the movement | string |
Movement Type
Movement | Description |
---|---|
collateralize_loan | A movement related to an increase in collateral held for any open loan(s) |
deposit | A deposit of additional assets into Zero Hash |
execution_fee | A movement due to incurred execution fees related to your trading activity on a Zero Hash liquidity venue |
final_settlement | A movement due to the full delivery and final settlement of a trade |
final_settlement_default | A movement due to a financially-settled trade whose final settlement obligation could not be fully settled due to a default |
final_settlement_default_fallback | A movement due to the financial settlement for the portion of a physically-settled trade's final settlement obligation that was not fully delivered due to a default |
final_settlement_default_partial | A movement due to the partial physical delivery of a physically-settled trade whose final settlement obligation could not be fully delivered due to a default |
initial_margin | A movement related to an increase or decrease in collateral held for any open position(s) |
interest_payment | A payment of interest for a loan |
loan_collateral_return | A movement related to a decrease in collateral held for any open loan(s) |
network_fee | A blockchain network fee incurred due to an on-chain movement related to your wallet |
principal_swap | A transfer of principal and collateral assets to open a loan |
repayment | A transfer to return principal and collateral for a loan that has terminated |
transfer | An internal transfer to or from an account at Zero Hash |
variation_margin | A payment made or collected due to changes in the market value of the position since the trade was executed or since the previous time the position was marked to market |
variation_margin_previous | A payment made or collected to settle a previously outstanding variation margin obligation |
withdrawal | A processed withdrawal from Zero Hash |
withdrawal_confirmed | Reversal of the temporary hold due to a withdrawal being processed |
withdrawal_pending | Temporary hold whilst a withdrawal is being processed |
commission | Commission charged on the trade |
bank_fee | Information field for platforms to provide if needed |
Transfer Type
Transfer | Description |
---|---|
trade_allocation | A trade movement to customer account for settlement |
commission_allocation | A commission movement to customer account for settlement |
commission_correction | An adjustment to commission |
Deposits
GET /deposits
const getDeposits = () => {
const body = {}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/deposits' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/deposits', options)
}
deposits = make_seed_request('GET', '/deposits', {})
Sample Response
{
"message": [
{
"settle_timestamp": 1590663417000,
"account_id": "80289ce5-072b-4739-929d-dcc5ccc542f3",
"movement_id": "21bdbb11-712f-4cb7-a178-4f277c80cde0",
"participant_code": "ABC123",
"account_group": "00SCXM",
"account_label": "general",
"asset": "BTC",
"amount": "4.0000",
"reference_id": "408482348dcb0e0331a9148d50f8c76db08138f63fb1586fcfc45200a91ccc5f",
"source": "tb1qne1pq8yampg83w4d5ywc79frdrub0az9eqpq9w",
"received_address": "tb1qf9bd2891mfhhz87o6ibairn86tadctgcn822pl",
"run_id": "12613"
}
],
"page": 1,
"total_pages": 1
}
Returns an array of deposits associated with the participant requesting. If you'd like to view your customer deposits in addition to yours, use the include_customer_deposits query parameter.
Query parameters include:
page
(optional) for paginating through your list of addressesasset
(optional) will filter to a specific assetinclude_customer_deposits
(optional) if true, will return customer deposits in addition to platform depositssettle_timestamp
filters deposits based on a given timestamp in milliseconds1593798130060
or nanoseconds1593798130060000000
using the following next params for the following filter types:[gt]
greater than a given timestamp, e.g.settle_timestamp[gt]=1593798130060
[gte]
greater than or equal to a given timestamp, e.g.settle_timestamp[gte]=1593798130060
[e]
equal to a given timestamp, e.g.settle_timestamp[e]=1593798130060
[lt]
less than a given timestamp, e.g.settle_timestamp[lt]=1593798130060
[lte]
lower than or equal to a given timestamp, e.g.settle_timestamp[lte]=1593798130060
- combinations are also possible, e.g. to find a trades between
1593798130555
and1593798130777
you can use the next combinationsettle_timestamp[gt]=1593798130555&settle_timestamp[lt]=1593798130777
participant_code
(optional) the participant_code to filter the response by, e.gparticipant_code=PLAT01
. Note thatparticipant_code
parameter does not work withinclude_customer_deposits
parameter.account_label
filters trades based on the account_label
Response:
Parameter | Description | Type |
---|---|---|
settle_timestamp | The timestamp for when the deposit was credited to the participant - this is also the movement_timestamp |
timestamp |
movement_id | A unique ID for the specific account update | string |
account_id | Unique ID of the specific account | string |
participant_code | The participant that was credited with the deposit, e.g. ABCDEF |
string |
account_group | The account group associated with the account_id that received the deposit, e.g. 00SCXM for the Seed Digital Commodities Market account group |
string |
account_label | The account label associated with the account | string |
asset | The asset code for the request, e.g. BTC |
string |
amount | The amount that was deposited into the account | number |
reference_id | This is an external identifier associated with the deposit, which is context-specific depending on the asset type and deposit source - wire, transfer or on-chain transaction ID | string |
source | The bank into which the fiat deposit was made or the blockchain address from which the crypto deposit came | string |
received_address | The blockchain address to which the crypto deposit went | string |
run_id | A unique ID for the particular run | string |
GET /deposits/digital_asset_addresses
const getDepositAddresses = () => {
const body = {}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/deposits/digital_asset_addresses' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/deposits/digital_asset_addresses',
options
)
}
depositAddresses = make_seed_request('GET', '/deposits/digital_asset_addresses', {})
Sample Response
{
"message": [
{
"created_at": 1561996924964,
"address": "2NCgV7BXXafJZ86utcYFs5m3tCpkcpLafeG",
"participant_code": "ABCDEF",
"asset": "BTC"
},
{
"created_at": 1561996924964,
"address": "0xe01ed9e684de649bfec799cd79f6c27335c23cb9",
"participant_code": "ABCDEF",
"asset": "ETH"
}
]
}
Returns an array of addresses associated with a participant's digital asset wallet. In order to GET deposit addresses for a participant_code other than yourself, you must have the submits_platform_withdrawals_for
relationship against said participant_code. Refer here for more information on relationship types.
Query parameters include:
participant_code
(optional) will return addresses for one of your customers - if not included, will default to the participant the API key was created forasset
(optional) will filter to a specific asset
Response:
Parameter | Description | Type |
---|---|---|
created_at | The timestamp for when the address was created | timestamp |
address | The digital wallet address | string |
asset | The asset code for the request, e.g. BTC |
string |
participant_code | The participant the request belongs to, e.g. ABCDEF |
string |
POST /deposits/digital_asset_addresses
const postDepositAddress = () => {
const body = { participant_code: 'ABCDEF', asset: 'BTC' }
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/deposits/digital_asset_addresses' + JSON.stringify(
body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
'https://api.zerohash.com/deposits/digital_asset_addresses',
options
)
}
depositAddress = make_seed_request('POST', '/deposits/digital_asset_addresses', {})
Sample Request
{
"participant_code": "ABCDEF",
"asset": "BTC"
}
Sample Response
{
"message": {
"created_at": 1561996924964,
"address": "2NCgV7BXXafJZ86utcYFs5m3tCpkcpLafeG",
"participant_code": "ABCDEF",
"account_label": "general",
"asset": "BTC"
}
}
Creates a new digital wallet deposit address for the asset and participant_code provided. In order to request a deposit address for a participant_code other than yourself, you must have the submits_platform_withdrawals_for
relationship against said participant_code. Refer here for more information on relationship types.
Parameter | Description | Type |
---|---|---|
participant_code | The participant code to create an address for | string |
asset | The asset code to make an address in, e.g. BTC |
string |
account_label (optional) | The account label associated with the deposit per participant and asset | string |
Response:
Parameter | Description | Type |
---|---|---|
created_at | The timestamp for when the address was created | timestamp |
address | The digital wallet address | string |
asset | The asset code tied to the address, e.g. BTC |
string |
participant_code | The participant the address belongs to, e.g. ABCDEF |
string |
account_label | The account label associated with the deposit per participant and asset, e.g. general |
string |
GET /deposits/fiat_accounts
const getFiatDepositAccounts = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/deposits/fiat_accounts' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/deposits/fiat_accounts', options)
}
zeroHashAccounts = make_seed_request('GET', '/deposits/fiat_accounts', {})
Sample Response
{
"message": {
"USD": [
{
"type": "united_states_wire",
"shortName": "BMO Harris",
"bankName": "BMO Harris Bank N.A.",
"bankPhysicalAddress": "123 Nowhere St.",
"accountNumber": "123-123-4",
"routingNumber": "07102343",
"recipientName": "Zero Hash LLC",
"recipientPhysicalAddress": "123 Nowhere St.",
"reference": "Your Participant Code"
},
{ ... }
],
"EUR": [ ... ]
}
}
Retrieves a list of all fiat deposit accounts available to you per fiat currency. The account details are keyed by currency code. Note: your participant code is provided as the reference field for each bank account. You must include this with any deposit to ensure that funds can be allocated correctly to your participant.
POST /deposits/fund
const postDepositsFund = () => {
const body = { participant_code: 'ABCDEF', asset: 'USD', amount: '2.99' }
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/deposits/fund' + JSON.stringify(
body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
'https://api.zerohash.com/deposits/fund',
options
)
}
depositsFund = make_seed_request('POST', '/deposits/fund', {})
Sample Request
{
"participant_code": "ABCDEF",
"asset": "USD",
"amount": "1.00"
}
Sample Response
{
"message": {
"amount": "1.00",
"participant_code": "ABCDEF",
"account_group": "ABCDEF",
"account_label": "general",
"account_type": "available",
"asset": "USD",
"reference_id": "21bdbb11-712f-4cb7-a178-4f277c80cde0"
}
}
Use this endpoint to fund a specified fiat account in Zero Hash’s CERT environment. This is NOT available in PROD. Using this endpoint is helpful when completing an integration to Zero Hash and wanting to enable end-to-end testing.
Parameter | Description | Type |
---|---|---|
participant_code | (required) This can be a linked participant to the Platform or the Platform can provide 00SCXM when looking to fund float accounts. | string |
asset | (required) The fiat asset that is looking to be funded. Right now this will only support USD. | string |
amount | (required) The amount that the Platform is looking to fund. This can only go out to two decimal places. | string |
account_label | (optional) This will default to general if not provided. Platforms may want to specify a specific account_label when looking to fund their rewards or awards float account. | string |
Please note that Zero Hash will default the account label to be the platform_code in the background to ensure the Platform is only funding accounts they manage.
Response:
Parameter | Description | Type |
---|---|---|
participant_code | The code of the participant that owns the account | string |
asset | The asset code for the specific account, e.g. USD | string |
amount | The amount that was deposited into the account | string |
account_label | The account label associated with the account | string |
account_group | The group that the account is a part of | string |
account_type | 'available', 'collateral', 'payable', 'receivable' or 'collateral_deficiency' | string |
reference_id | This is an external identifier associated with the deposit, which is context-specific depending on the asset type and deposit source - wire, transfer or on-chain transaction ID | string |
Withdrawals
GET /withdrawals/requests
const getWithdrawalRequests = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/requests' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/withdrawals/requests', options)
}
withdrawalRequests = make_seed_request('GET', '/withdrawals/requests', {})
Sample Response
{
"message": [
{
"id": 78,
"withdrawal_account_id": 51,
"participant_code": "ABCDEF",
"requestor_participant_code": "ABCDEF",
"requested_amount": "23",
"settled_amount": "21",
"status": "APPROVED",
"asset": "BTC",
"account_group": "00SCXM",
"transaction_id": null,
"requested_timestamp": 1554395972174,
"gas_price": null,
"client_withdrawal_request_id": null,
"on_chain_status": "PENDING",
"fee_amount": "0.003163149641603118"
}
],
"page": 1,
"total_pages": 1
}
Returns an array of all withdrawal requests created by users as part of your participant.
Query parameters include:
participant_code
(optional) will default to the participant the API key was created forpage
(optional) for paginating through your list of addressesstatus
(optional) for selecting requests with specific statusAPPROVED
,REJECTED
etc.gas_price
(optional) for selecting requests with specific gas priceclient_withdrawal_request_id
(optional) for selecting requests with specific client withdrawal request idon_chain_status
(optional) for selecting on chain with specific status. You can useCONFIRMED
orPENDING
.requested_timestamp
filters withdrawal requests based on a given timestamp in milliseconds1593798130060
or nanoseconds1593798130060000000
using the following params for the following filter types:[gt]
greater than a given timestamp, e.g.requested_timestamp[gt]=1593798130060
[gte]
greater than or equal to a given timestamp, e.g.requested_timestamp[gte]=1593798130060
[e]
equal to a given timestamp, e.g.requested_timestamp[e]=1593798130060
[lt]
less than a given timestamp, e.g.requested_timestamp[lt]=1593798130060
[lte]
lower than or equal to a given timestamp, e.g.requested_timestamp[lte]=1593798130060
- combinations are also possible, e.g. to find a withdrawal requests between
1593798130555
and1593798130777
you can use the next combinationrequested_timestamp[gt]=1593798130555&requested_timestamp[lt]=1593798130777
account_label
filters trades based on the account_label
Response:
Parameter | Description | Type |
---|---|---|
id | The withdrawal request ID | number |
client_withdrawal_request_id | A unique identifier for the withdrawal, generally produced by the Platform on which the trade was executed Note: this must be unique, per platform, per 24 hour period |
string |
withdrawal_account_id | The ID of the withdrawal account the address belongs to | number |
asset | The asset code for the request, e.g. BTC |
string |
participant_code | The participant the request belongs to, e.g. ABCDEF |
string |
requestor_participant_code | The participant code of the requestor, e.g. ABCDEF |
string |
account_group | The account group the request was made against, e.g. 00SCXM for the Seed Digital Commodities Market account group |
string |
requested_amount | The initially requested amount, e.g. 100.10 |
string |
settled_amount | The settled amount. This can be less than or equal to the requested_amount, e.g. 99 |
string or null |
transaction_id | The on-chain transaction id once the withdrawal has been confirmed | string or null |
status | The current status of the withdrawal request | string |
requested_timestamp | The timestamp for when the withdrawal request was requested | timestamp |
gas_price | The transaction fee payable on the Ethereum network If the asset is not an ERC-20 token, this field will always be null |
string or null |
on_chain_status | The status of the withdrawal on the blockchain. Could be PENDING or CONFIRMED more details here. | string |
fee_amount | will return the network fee amount | string |
GET /withdrawals/requests/:id
const getWithdrawalRequests = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/requests/78' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/requests/78',
options
)
}
withdrawalRequests = make_seed_request('GET', '/withdrawals/requests/78', {})
Sample Response
{
"message": [
{
"id": 78,
"withdrawal_account_id": 51,
"participant_code": "ABCDEF",
"requestor_participant_code": "ABCDEF",
"requested_amount": "23",
"settled_amount": "21",
"status": "APPROVED",
"asset": "BTC",
"account_group": "00SCXM",
"transaction_id": null,
"requested_timestamp": 1554395972174,
"gas_price": null,
"client_withdrawal_request_id": null,
"on_chain_status": "PENDING",
"fee_amount": "0.003163149641603118"
}
]
}
Returns a specific withdrawal request associated with your participant or platform.
See GET /withdrawals/requests for response field descriptions.
POST /withdrawals/requests
Sample Request
const postWithdrawalRequest = () => {
const body = {
withdrawal_account_id: 123,
participant_code: "ABCDEF",
amount: "20",
asset: "BTC",
account_group: "00SCXM"
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/withdrawals/requests' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/withdrawals/requests`, options)
}
resp = make_seed_request('POST', '/withdrawals/requests', {})
Sample Response
{
"message": {
"id": 117,
"withdrawal_account_id": 146,
"participant_code": "ABCDEF",
"requestor_participant_code": "ABCDEF",
"account_group": "00SCXM",
"requested_amount": "20",
"settled_amount": null,
"status": "APPROVED",
"asset": "BTC",
"requested_timestamp": 1561996924964,
"gas_price": null,
"client_withdrawal_request_id": null,
"on_chain_status": "PENDING",
"fee_amount": "0.003163149641603118"
}
}
Creates new withdrawal requests to be settled. Withdrawal requests created through the API go directly into an APPROVED
state. To retrieve withdrawal account IDs use the GET /withdrawals/digital_asset_addresses
and GET /withdrawals/fiat_accounts
endpoints.
There are 3 ways to submit withdrawal requests:
- The first, standard method uses a
withdrawal_account_id
to choose the location to withdrawal to, which can be for a fiat currency or a digital asset. The account must be in anAPPROVED
state before submitting withdrawal requests to it. - The second method allows for submitting a digital asset
address
instead of thewithdrawal_account_id
. When POSTing anaddress
, Zero Hash will first scan to see if you already have an existingwithdrawal_account_id
for that destination, and if not, it will create one automatially and provide you thewithdrawal_account_id
in response. This is not available as standard. Please contact us if you'd like to learn more about this option. - The third method allows for submitting a fiat withdrawal
account{}
instead of thewithdrawal_account_id
. When POSTing anaccount{}
, Zero Hash will first scan to see if you already have an existingwithdrawal_account_id
for that destination, and if not, it will create one automatially and provide you thewithdrawal_account_id
in response. This is not available as standard. Please contact us if you'd like to learn more about this option.
Request body:
Parameter | Description | Type |
---|---|---|
client_withdrawal_request_id | A unique identifier for the withdrawal, generally produced by the Platform on which the trade was executed Note: this must be unique, per platform, per 24 hour period |
string |
withdrawal_account_id | The whitelisted withdrawal account or address to withdraw funds to Note: only one of withdrawal_account_id , address or account{} can be submitted per withdrawal, but Zero Hash will always respond with withdrawal_account_id |
string |
address | The digital asset address to withdraw funds to, which may or may not already exist in Zero Hash as an approved withdrawal_account_id Note: only one of withdrawal_account_id , address or account{} can be submitted per withdrawal, but Zero Hash will always respond with withdrawal_account_id |
string |
account{} | The fiat account to withdraw funds to, which may or may not already exist in Zero Hash as an approved withdrawal_account_id Note: only one of withdrawal_account_id , address or account{} can be submitted per withdrawal, but Zero Hash will always respond with withdrawal_account_id |
object |
participant_code | The participant code against whom the withdrawal will be made | string |
account_group | The account group to withdraw against, e.g. 00SCXM for the Seed Digital Commodities Market account group |
string |
account_label | The account label associated with the account | string |
amount | The amount to withdraw | string |
asset | The asset code for the withdrawal request, e.g. BTC |
string |
destination_tag | For tag-based assets, please provide the memo id/destination tag value in this field. For more information on when and how to populate this field, please refer here | string |
no_destination_tag | The value should be true or false. For more information on when and how to populate this field, please refer here | boolean |
Account field shape:
Parameter | Description | Type |
---|---|---|
name | The nickname given to the withdrawal account Note: Zero Hash will append the last 4 digits of the account number to this when saving it |
string |
limit | The limit applied to the account on a per-withdrawal basis | number |
type | The type of account: REAL_TIME_FIAT for 24/7 USD withdrawals, DOMESTIC_FIAT for US wires or INTERNATIONAL_FIAT for international wires |
string |
beneficiary_name | The owner of the account at the withdrawal destination | string |
account_number | The unique IBAN or account number for the final withdrawal destination | string |
bank_name | The name of the destination financial institution | string |
routing_number | For US wires, the ABA routing number identifies the destination financial institution | string |
swift_code | SWIFT code, if applicable | string |
recipient_instructions | Any additional instructions on the account | string |
intermediary_ bank_name |
Intermediary bank name, if applicable | string |
intermediary_ bank_code_type |
Intermediary bank identifier code type, if applicableOptions include SWIFT |
string |
intermediary_ bank_code |
Intermediary bank identifier that corresponds to intermediary_bank_code_type , if applicable |
string |
intermediary_ bank_account_number |
Intermediary bank IBAN or account number, if applicable | string |
correspondent_ bank_name |
Correspondent bank name, if applicable | string |
correspondent_ bank_code_type |
Correspondent bank identifier code type, if applicableOptions include SWIFT |
string |
correspondent_ bank_code |
Correspondent bank identifier that corresponds to correspondent_bank_code_type , if applicable |
string |
correspondent_ bank_account_number |
Correspondent bank IBAN or account number, if applicable | string |
DELETE /withdrawals/requests/:id
const deleteWithdrawalRequest = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'DELETE' + '/withdrawals/requests' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
json: true
}
const withdrawalRequestId = 1
return request.delete(
`https://api.zerohash.com/withdrawals/requests/${withdrawalRequestId}`,
options
)
}
resp = make_seed_request('DELETE', '/withdrawals/requests/1', {})
Sample Response
{
"message": {
"id": 1,
"withdrawal_account_id": 146,
"participant_code": "ABCDEF",
"requestor_participant_code": "ABCDEF",
"requested_amount": "20",
"account_group": "00SCXM",
"settled_amount": null,
"status": "REJECTED",
"asset": "BTC",
"requested_timestamp": 1561996924964,
"gas_price": null,
"client_withdrawal_request_id": null,
"on_chan_status": null,
"fee_amount": "0.003163149641603118"
}
}
Rejects a pending withdrawal request.
GET /withdrawals/digital_asset_addresses
const getWithdrawalAddresses = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/digital_asset_addresses' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
json: true
}
return request.get(
`https://api.zerohash.com/withdrawals/digital_asset_addresses?participant_code=YOUR_PARTICIPANT_CODE`,
options
)
}
withdrawalAddresses = make_seed_request('GET', '/withdrawals/digital_asset_addresses?participant_code=YOUR_PARTICIPANT_CODE', {})
Sample Response
{
"message": [
{
"withdrawal_account_id": 123,
"name": "Fund ABC Wallet",
"address": "M9zjMhjaPfwaeyeH2SY6aWyGqdTS9feg8Z",
"status": "APPROVED",
"limit": 1000,
"asset": "LTC",
"last_update": 1554395972174,
"submitted_address": "33nb3pKcSZ69rUNNvZYkksisWvrzCmi3Jt",
"participant_code": "ABCDEF"
}
],
"page": 1,
"total_pages": 1
}
Returns an array of all withdrawal addresses created by users as part of your participant.
Query parameters include:
participant_code
(optional) will default to the participant the API key was created forpage
(optional) for paginating through your list of addresses
Response:
Parameter | Description | Type |
---|---|---|
withdrawal_account_id | The ID of the withdrawal account the address belongs to | number |
name | The nickname the address was given when it was created | string |
address | The blockchain address | string |
status | The approval status of the address | string |
asset | The asset code for the specific account, e.g. BTC |
string |
limit | The limit applied to the account on a per-withdrawal basis | number |
last_update | Timestamp for when the withdrawal address last update | timestamp |
submitted_address | This is the original value for an address submitted by you, that was converted into a newer format supported by Zero Hash - this will be null if no conversion is necessary | string |
participant_code | The participant the request belongs to, e.g. ABCDEF |
string |
GET /withdrawals/digital_asset_addresses/:id
const getWithdrawalAddresses = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/digital_asset_addresses/:id' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/digital_asset_addresses/:id',
options
)
}
withdrawalAddresses = make_seed_request('GET', '/withdrawals/digital_asset_addresses/:id', {})
Sample Response
{
"message": {
"withdrawal_account_id": 123,
"name": "Fund ABC Wallet",
"address": "M9zjMhjaPfwaeyeH2SY6aWyGqdTS9feg8Z",
"status": "APPROVED",
"limit": 1000,
"asset": "LTC",
"last_update": 1554395972174,
"submitted_address": "33nb3pKcSZ69rUNNvZYkksisWvrzCmi3Jt",
"participant_code": "ABCDEF"
}
}
Returns a specific crypto withdrawal account associated with your participant or platform.
See GET /withdrawals/digital_asset_addresses for response field descriptions.
GET /withdrawals/fiat_accounts
const getFiatWithdrawalAccounts = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/fiat_accounts' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/fiat_accounts',
options
)
}
zeroHashAccounts = make_seed_request('GET', '/withdrawals/fiat_accounts', {})
Sample Response
{
"message": [
{
"withdrawal_account_id": 286,
"name": "Primary (1234)",
"status": "PENDING_CREATION",
"asset": "USD",
"limit": 750000,
"type": "DOMESTIC_FIAT",
"beneficiary_name": "John Doe",
"account_number": "1231234",
"bank_name": "BMO Harris",
"routing_number": "07102343",
"swift_code": null,
"recipient_instructions": null,
"intermediary_bank_name": null,
"intermediary_bank_code_type": null,
"intermediary_bank_code": null,
"intermediary_bank_account_number": null,
"correspondent_bank_name": null,
"correspondent_bank_code_type": null,
"correspondent_bank_code": null,
"correspondent_bank_account_number": null,
"last_update": 1571175076187,
"participant_code": "ABCDEF"
},
{ ... }
],
"page": 1,
"total_pages": 1
}
Retrieves a list of all whitelisted fiat withdrawal accounts.
Parameter | Description | Type |
---|---|---|
withdrawal_account_id | The ID of the withdrawal account | number |
name | The nickname given to the withdrawal account | string |
status | The approval status of the withdrawal account | string |
asset | The asset code for the specific withdrawal account, e.g. USD |
string |
limit | The limit applied to the account on a per-withdrawal basis | number |
type | The type of account: REAL_TIME_FIAT for 24/7 USD withdrawals, DOMESTIC_FIAT for US wires or INTERNATIONAL_FIAT for international wires |
string |
beneficiary_name | The owner of the account at the withdrawal destination | string |
account_number | The unique IBAN or account number for the final withdrawal destination | string |
bank_name | The name of the destination financial institution | string |
routing_number | For US wires, the ABA routing number identifies the destination financial institution | string |
swift_code | SWIFT code, if applicable | string |
recipient_instructions | Any additional instructions on the account | string |
intermediary_ bank_name |
Intermediary bank name, if applicable | string |
intermediary_ bank_code_type |
Intermediary bank identifier code type, if applicableOptions include SWIFT |
string |
intermediary_ bank_code |
Intermediary bank identifier that corresponds to intermediary_bank_code_type , if applicable |
string |
intermediary_ bank_account_number |
Intermediary bank IBAN or account number, if applicable | string |
correspondent_ bank_name |
Correspondent bank name, if applicable | string |
correspondent_ bank_code_type |
Correspondent bank identifier code type, if applicableOptions include SWIFT |
string |
correspondent_ bank_code |
Correspondent bank identifier that corresponds to correspondent_bank_code_type , if applicable |
string |
correspondent_ bank_account_number |
Correspondent bank IBAN or account number, if applicable | string |
last_update | Timestamp for when the withdrawal address last update | timestamp |
submitted_address | This is the original value for an address submitted by you, that was converted into a newer format supported by Zero Hash - this will be null if no conversion is necessary | string |
participant_code | The participant the request belongs to, e.g. ABCDEF |
string |
GET /withdrawals/fiat_accounts/:id
const getFiatWithdrawalAccounts = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/fiat_accounts/:id' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/fiat_accounts/:id',
options
)
}
zeroHashAccounts = make_seed_request('GET', '/withdrawals/fiat_accounts/:id', {})
Sample Response
{
"message": {
"withdrawal_account_id": 286,
"name": "Primary (1234)",
"status": "PENDING_CREATION",
"asset": "USD",
"limit": 750000,
"type": "DOMESTIC_FIAT",
"beneficiary_name": "John Doe",
"account_number": "1231234",
"bank_name": "BMO Harris",
"routing_number": "07102343",
"swift_code": null,
"recipient_instructions": null,
"intermediary_bank_name": null,
"intermediary_bank_code_type": null,
"intermediary_bank_code": null,
"intermediary_bank_account_number": null,
"correspondent_bank_name": null,
"correspondent_bank_code_type": null,
"correspondent_bank_code": null,
"correspondent_bank_account_number": null,
"last_update": 1571175076187,
"participant_code": "ABCDEF"
}
}
Returns a specific fiat withdrawal account associated with your participant or platform.
See GET /withdrawals/fiat_accounts for response field descriptions.
Withdrawal Request Status
Status | Description |
---|---|
PENDING | The request has been created and is pending approval from users |
APPROVED | The request is approved but not settled |
REJECTED | The request is rejected and in a terminal state |
SETTLED | The request was settled and sent for confirmation onchain if a digital asset |
Withdrawal Account Status
Status | Description |
---|---|
PENDING_CREATION | Account is awaiting approval |
APPROVED | The account is approved for use |
REJECTED | The account was rejected for use |
DELETED | The account was deleted, removing it from view in the portal |
PENDING_CHANGE | DEPRECATED The address is awaiting a change approval for either unlocking or changing the limit |
GET /withdrawals/locked_network_fee
const getLockedNetworkFee = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/locked_network_fee' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/locked_network_fee?participant_code=CUST01&account_group=PLAT01&amount=.023&destination_tag=&asset=ETH&withdrawal_address=0x48b358a64eb0cDfeD6f369B7610Be84cBC6D3Ad7',
options
)
}
res = make_seed_request('GET', '/withdrawals/locked_network_fee?participant_code=CUST01&account_group=PLAT01&amount=.023&destination_tag=&asset=ETH&withdrawal_address=0x48b358a64eb0cDfeD6f369B7610Be84cBC6D3Ad7', {})
Sample Response
{
"message": {
"withdrawal_quote_id": "b30739eb-173d-45f9-a03e-281e7c4db22c",
"withdrawal_account_id": "",
"withdrawal_address": "0x48b358a64eb0cDfeD6f369B7610Be84cBC6D3Ad7",
"destination_tag": "",
"amount": "0.023",
"amount_notional": "30.15",
"max_amount": false,
"network_fee": "0.000546004133871",
"network_fee_notional": "0.72",
"net_withdrawal_quantity": "0.022453995866129",
"net_withdrawal_notional": "29.44",
"asset": "ETH",
"participant_code": "CUST01",
"account_group": "PLAT01",
"account_label": "general"
}
}
GET /withdrawals/locked_network_fee and POST /withdrawals/execute can be used to create a withdrawal locked network fee quote and execute it on-chain. To use these endpoints a Platform needs to be configured for netted withdrawals, which is a new withdrawal fee payor setting.
All withdrawals processed using these endpoints will have the locked network fee deducted from the withdrawal amount that is actually processed on-chain. Additionally all network fees are quoted as the asset being requested to be withdrawn. Network fees are locked for 30 seconds, after this time if a Platform tries to execute the locked network fee quote an error response will be returned.
Query parameters include:
participant_code
of the participant that is requesting the locked network feeaccount_group
of the account_group for the source account that the withdrawal should be coming fromaccount_label
of the account_label for the source account that the withdrawal should be coming fromasset
the asset to be withdrawnamount
the requested withdrawal amount (required and must be positive if max_amount is false). If max_amount = true and amount > 0 then the API will use the max_amount instead of the amount value.max_amount
will default to “false”. If set to “true” the API will retrieve the provided participant’s account balance for the given asset and generate a withdrawal for the entire balance to the destination address (required if amount is 0.00 or not provided)withdrawal_account_id
is associated with the destination address (required if withdrawal_address is not present)withdrawal_address
the on-chain address that shall receive the crypto asset (required if withdrawal_account_id is not present)destination_tag
(optional) for tag-based assets, please provide the memo id/destination tag value in this field. For more information on when and how to populate this field, please refer hereno_destination_tag
(optional) the value should be true or false. For more information on when and how to populate this field, please refer here. Supported values aretrue
orfalse
For more details on how the endpoints function see here.
Response:
Parameter | Description | Type |
---|---|---|
account_group | The account_group for the source account that the withdrawal was processed from. | string |
account_label | The account_label for the source account that the withdrawal was processed from. | string |
amount | The requested withdrawal amount. | string |
amount_notional | The requested withdrawal amount notional value. | string |
asset | The asset that has been withdrawn. | string |
destination_tag | The destination tag for the withdrawal. | string |
no_destination_tag | If a destination tag is specified for the withdrawal. | boolean |
max_amount | The max amount flag. | string |
net_withdrawal_notional | amount minus network_fee notional value. | string |
net_withdrawal_quantity | amount minus network_fee, in terms of quantity. | string |
network_fee | The network fee quantity being deducted from the requested withdrawal amount. | string |
network_fee_notional | The network fee notional value. | string |
participant_code | The participant that requested the withdrawal. | string |
withdrawal_address | The on-chain address that received the crypto asset. | string |
withdrawal_quote_id | The unique ID that is associated with the locked network fee. | string |
withdrawal_account_id | The withdrawal account ID that is associated with the destination address. | string |
POST /withdrawals/execute
const postWithdrawalExecuteRequest = () => {
const body = {
withdrawal_quote_id: "b30739eb-173d-45f9-a03e-281e7c4db22c"
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/withdrawals/execute' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/withdrawals/execute`, options)
}
resp = make_seed_request('POST', '/withdrawals/execute', {})
Sample Response
{
"message": {
"request_id": "c9d19acc-96bc-4c29-9708-50912fd174cf",
"withdrawal_quote_id": "b30739eb-173d-45f9-a03e-281e7c4db22c",
"withdrawal_request_id": "58672",
"participant_code": "CUST01",
"account_group": "PLAT01",
"account_label": "general",
"withdrawal_address": "0x48b358a64eb0cDfeD6f369B7610Be84cBC6D3Ad7",
"destination_tag": "",
"asset": "ETH",
"amount": "0.023",
"amount_notional": "30.15",
"network_fee": "0.000546004133871",
"network_fee_notional": "0.72",
"on_chain_status": "PENDING"
}
}
This endpoint is used to execute a locked network fee quote. This will tell Zero Hash to process the withdrawal on-chain.
Request body:
Parameter | Description | Type |
---|---|---|
withdrawal_quote_id | The unique ID that is associated with the locked network fee. This will be required to execute the withdrawal. | string |
Response:
Parameter | Description | Type |
---|---|---|
account_group | The account_group for the source account that the withdrawal was processed from. | string |
account_label | The account_label for the source account that the withdrawal was processed from. | string |
amount | The requested withdrawal amount. | string |
amount_notional | The requested withdrawal amount notional value. | string |
asset | The asset that has been withdrawn. | string |
destination_tag | The destination tag for the withdrawal. | string |
no_destination_tag | If a destination tag is specified for the withdrawal. | boolean |
network_fee | The network fee quantity being deducted from the requested withdrawal amount. | string |
network_fee_notional | The network fee notional value. | string |
on_chain_status | The status of the withdrawal on the blockchain. Could be PENDING or CONFIRMED more details here. | string |
participant_code | The participant that requested the withdrawal. | string |
request_id | The unique Id that is associated with this http request. | string |
withdrawal_address | The on-chain address that received the crypto asset. | string |
withdrawal_quote_id | The unique ID that is associated with the locked network fee. | string |
withdrawal_request_id | The unique Id that is associated with this withdrawal request. | string |
GET /withdrawals/estimate_network_fee
const getEstimateNetworkFee = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/estimate_network_fee' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/estimate_network_fee',
options
)
}
estimateNetworkFee = make_seed_request('GET', '/withdrawals/estimate_network_fee', {})
Sample Response
{
"message": {
"underlying": "BTC",
"quoted_currency": "USD",
"network_fee_asset": "BTC",
"network_fee_quantity": "0.000172825",
"total_notional": "3.3733791241663290125"
}
}
Retrive the estimate network fee. The following query parameters are required:
underlying
quoted_currency
Optional query parameters include:
amount
The amount of theunderlying
currencydestination_address
The destination_address is the receiving address for the withdrawal requestcontract_call
In a future release, this field will denote if the destination address is a smart contract address. False is the only acceptable value for now.
Parameter | Description | Type |
---|---|---|
underlying | The asset being valued | string |
quoted_currency | The asset in which the underlying is being valued |
string |
network_fee_asset | The network fee asset | string |
network_fee_quantity | The quantity of network fee | string |
total_notional | fee_amount x (index price for fee_currency quoted in quoted_currency) | string |
GET /withdrawals/validate_address
const getValidateAddress = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/withdrawals/validate_address?asset=BTC&address=1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(
'https://api.zerohash.com/withdrawals/validate_address?asset=BTC&address=1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
options
)
}
resp = make_seed_request('GET', '/withdrawals/validate_address?asset=BTC&address=1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', {})
Sample Response
{
"message": "the address is valid"
}
The following query parameters are required:
asset
address
Optional query parameters include:
destination_tag
(optional) The destination tag for the address being validated.
Parameter | Description | Type |
---|---|---|
asset | The asset code for the address being validated, e.g. XRP |
string |
address | The digital wallet address | string |
destination_tag | For tag-based assets, please provide the memo id/destination tag value in this field. For more information on when and how to populate this field, please refer here | string |
Transfers
GET /transfers
const getTransfers = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/transfers' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/transfers', options)
}
resp = make_seed_request('GET', '/transfers', {})
Sample Response
{
"message": [
{
"id": 39,
"client_transfer_id" : "5fed7a1d-1cd3-4be7-9d63-dd67805d441d",
"created_at": "2020-09-01T20:53:31.653Z",
"updated_at": "2020-09-01T20:53:31.653Z",
"status": "settled",
"from_participant_code": "ABC123",
"from_account_group": "UNALLOCATED",
"from_account_label": "general",
"to_participant_code": "DEMO01",
"to_account_group": null,
"to_account_label": "general",
"asset": "BTC",
"amount": "20.00",
"movement_id": "1902a0eb-a925-4d08-bcad-ea8ed4696a24",
"admin_transfer": true
},
{
"id": 38,
"client_transfer_id": null,
"created_at": "2020-09-01T20:53:31.406Z",
"updated_at": "2020-09-01T20:53:31.406Z",
"status": "approved",
"from_participant_code": "ABC123",
"from_account_group": "UNALLOCATED",
"from_account_label": "general",
"to_participant_code": "ABC123",
"to_account_group": "XYZ456",
"to_account_label": "general",
"asset": "USD",
"amount": "100.00",
"movement_id": null,
"admin_transfer": false
}
],
"page": 1,
"total_pages": 1
}
Returns an array of all transfers requests made to or from your participant, or to or from your platform's account group.
Query parameters include:
client_transfer_id
(optional) the Platform-dictated unique identifier for the transferpage
(optional) for paginating through the transferspage_size
(optional) the number of transfers per pagefrom_participant_code
(optional) the participant where the transfer originated fromto_participant_code
(optional) the participant code where the transfer was wired torequested_timestamp
(optional) filters transfers based on a given timestamp in milliseconds1593798130060
or nanoseconds1593798130060000000
using the following params for the following filter types:[gt]
greater than a given timestamp, e.g.requested_timestamp[gt]=1593798130060
[gte]
greater than or equal to a given timestamp, e.g.requested_timestamp[gte]=1593798130060
[e]
equal to a given timestamp, e.g.requested_timestamp[e]=1593798130060
[lt]
less than a given timestamp, e.g.requested_timestamp[lt]=1593798130060
[lte]
lower than or equal to a given timestamp, e.g.requested_timestamp[lte]=1593798130060
- Combinations are also possible, e.g. to find a transfers between
1593798130555
and1593798130777
you can use the next combinationrequested_timestamp[gt]=1593798130555&requested_timestamp[lt]=1593798130777
Response:
Parameter | Description | Type |
---|---|---|
id | The transfer request ID | number |
client_transfer_id | Optional unique identifier for the transfer. Note: this must be unique, per platform, per 72 hour period |
string |
created_at | The timestamp when the transfer request was requested | timestamp |
updated_at | The timestamp when the transfer request was last updated | timestamp |
status | The current status of the transfer request | string |
from_participant_code | The source participant for the transfer to, e.g. ABCDEF |
string |
from_account_group | The source account group for the transfer, e.g. ABCDEF Note: this may be null if the requesting participant is not authorized to see the source account group |
string |
from_account_label | The source account label for the transfer, e.g. general |
string |
to_participant_code | The destination participant for the transfer, e.g. ABCDEF |
string |
to_account_group | The destination account group for the transfer, e.g. ABCDEF Note: this may be null if the requesting participant is not authorized to see the destination account group |
string |
to_account_label | The destination account label for the transfer, e.g. general |
string |
asset | The asset code for the request, e.g. USD |
string |
amount | The amount or quantity transferred, e.g. 100 |
string |
movement_id | A unique ID for the specific account update Note: this will be null until the transfer updates to settled |
string |
Transfer Request Status
Status | Description |
---|---|
pending | The request has been created and is pending approval from users |
approved | The request is approved but not settled |
canceled | The request is canceled and in a terminal state |
rejected | The request is rejected and in a terminal state |
settled | The request was settled and is in a terminal state |
GET /transfers/:id
const getTransfers = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/transfers/39' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/transfers/39', options)
}
resp = make_seed_request('GET', '/withdrawals/requests/39', {})
Sample Response
{
"message": {
"id": 39,
"client_transfer_id": null,
"created_at": "2020-09-01T20:53:31.653Z",
"updated_at": "2020-09-01T20:53:31.653Z",
"status": "settled",
"from_participant_code": "ABC123",
"from_account_group": "UNALLOCATED",
"to_participant_code": "DEMO01",
"to_account_group": null,
"asset": "BTC",
"amount": "20.00",
"movement_id": "1902a0eb-a925-4d08-bcad-ea8ed4696a24",
"admin_transfer": true
}
}
Returns single transfer made to or from your participant, or to or from your platform's account group.
See GET /transfers for response field descriptions.
POST /transfers
const postTransfers = () => {
const body = {
from_participant_code: "ABC123",
from_account_group: "UNALLOCATED",
to_participant_code: "DEMO01",
to_account_group: "UNALLOCATED",
asset: "USD",
amount: "1"
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/transfers' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post('https://api.zerohash.com/transfers', options)
}
resp = make_seed_request('POST', '/transfers', {})
Creates new transfer request. Note: you can only submit transfers between your own accounts. To submit transfers on behalf of others, you need the submits_platform_transfers_for
relationship. Transfer requests created through the API go directly into an APPROVED
state.
Request body:
Parameter | Description | Type |
---|---|---|
client_transfer_id | Optional unique identifier for the transfer. Note: this must be unique, per platform, per 72 hour period |
string |
from_participant_code | The source participant for the transfer to, e.g. ABCDEF |
string |
from_account_group | The source account group for the transfer, e.g. ABCDEF |
string |
from_account_label | The source account label for the transfer, e.g. general |
string |
to_participant_code | The destination participant for the transfer, e.g. ABCDEF |
string |
to_account_group | The destination account group for the transfer, e.g. ABCDEF |
string |
to_account_label | The destination account label for the transfer, e.g. general |
string |
asset | The asset code for the request, e.g. USD |
string |
amount | The amount or quantity transferred, e.g. 100 |
string |
client_transfer_id | string |
Sample Response
{
"message": [
{
"id": 39,
"client_transfer_id": null,
"created_at": "2020-09-01T20:53:31.653Z",
"updated_at": "2020-09-01T20:53:31.653Z",
"status": "settled",
"from_participant_code": "ABC123",
"from_account_group": "UNALLOCATED",
"from_account_label": "general",
"to_participant_code": "DEMO01",
"to_account_group": "UNALLOCATED",
"to_account_label": "general",
"asset": "BTC",
"amount": "20.00",
"movement_id": "1902a0eb-a925-4d08-bcad-ea8ed4696a24",
"admin_transfer": true
}
]
}
See GET /transfers for response field descriptions.
Participants
GET /participants
const getParticipants = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/participants' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/participants', options)
}
resp = make_seed_request('GET', '/participants', {})
Sample Response
{
"message": [
{
"participant_code": "123XYZ",
"custodian_participant_code": "CUST01",
"participant_name": "Trading Firm LLC",
"credit_limit": "50000",
"status": "approved",
"email": "customer@gmail.com",
"reason_code": "compliance_issue",
"updated_at": 1680643465352
},
{
"participant_code": "ABC456",
"participant_name": "Lots of Capital LLC",
"credit_limit": null,
"status": "approved",
"email": null,
"reason_code": null,
"updated_at": 1680643465352
}
],
"page": 1,
"total_pages": 1,
"page_size": 50,
"count": 2
}
Returns a list of all participants to which you are associated.
Query parameters include:
email
(optional) filters to a particular emailparticipant_code
(optional) filters to a particular participant codepage
(optional) for paginating through the participantsminors
(optional) [true or false] if true, returns a list of minors and their associated custodiansstatus
(optional) the current status of the participant. read more about statuses here
Response parameters listed below
Parameter | Description | Type |
---|---|---|
participant_code | Unique participant code | string |
custodian_participant_code | Unique participant code of the associated custodian | string |
participant_name | Name of participant | string |
credit_limit | Client-determined credit limit. used purely for reporting purposes at this time | string |
Email associated with the participant. If the participant is institutional, this field will be null | string | |
status | The current status of the participant. read more about statuses here | string |
reason_code | (optional) if the participant has changed statuses, the reason code will show compliance_issue, user_request, or risk_cleared | string |
updated_at | Last update timestamp | number |
GET /participants/:email
const getParticipants = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/participants/{email}' + '{}'
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get('https://api.zerohash.com/participants/{email}', options)
}
resp = make_seed_request('GET', '/participants/{email}', {})
Sample Response
{
"message": {
"participant_code": "123XYZ",
"email": "customer@gmail.com"
}
}
Returns a participant to which you are associated by an email. As an alternative to using the email
query parameter described above within the GET /participants endpoint, this is a lighter-weight and dedicated endpoint to filter participants by email.
Query parameters include:
email
filters to a particular email
Response parameters listed below
Parameter | Description | Type |
---|---|---|
participant_code | Unique participant code | string |
Email associated with the participant | string |
POST /participants/customers/new
const postParticipantCustomer = () => {
const body = {
request_id: '7fbab305-2679-4279-808b-9b7a63a55c85',
first_name: 'John',
last_name: 'Smith',
email: 'email-example@mail.com',
phone_number: '15557778888',
address_one: '1 Main St.',
address_two: 'Suite 1000',
city: 'Chicago',
state: 'IL',
zip: '12345',
country: 'United States',
date_of_birth: '1985-09-02',
citizenship: 'United States',
tax_id: '123456789',
risk_rating: 'low',
kyc: 'pass',
kyc_timestamp: 1603378501285,
sanction_screening: 'pass',
sanction_screening_timestamp: 1603378501285,
signed_timestamp: 1603378501286,
metadata: {}
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/participants/customers/new' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/customers/new`,
options
)
}
resp = make_seed_request('POST', '/participants/customers/new', {})
Sample Request
{
"request_id": "7fbab305-2679-4279-808b-9b7a63a55c85",
"first_name": "John",
"last_name": "Smith",
"email": "email-example@mail.com",
"phone_number": "15557778888",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"state": "IL",
"zip": "12345",
"country": "United States",
"date_of_birth": "1985-09-02",
"citizenship": "United States",
"tax_id": "123456789",
"risk_rating": "low",
"kyc": "pass",
"kyc_timestamp": 1603378501285,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501285,
"signed_timestamp": 1603378501286,
"metadata": {}
}
Sample Response
{
"message": {
"first_name": "John",
"last_name": "Smith",
"email": "email-example@mail.com",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"country": "United States",
"state": "IL",
"city": "Chicago",
"zip": "12345",
"date_of_birth": "1985-09-02",
"citizenship": "United States",
"tax_id": "123456789",
"id_number_type": null,
"id_number": null,
"non_us_other_type": null,
"id_issuing_authority": null,
"risk_rating": "low",
"kyc": "pass",
"kyc_timestamp": 1603378501285,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501285,
"signed_timestamp": 1603378501286,
"metadata": {},
"platform_code": "ABC123",
"participant_code": "XYZ456"
}
}
Submits a customer to your platform.
Request body:
Parameter | Description | Type |
---|---|---|
request_id | A universally unique identifier (UUID) for this request, optional Note: To ensure idempotence, it is recommended to include this parameter |
string |
first_name | The first name of the customer, required | string |
last_name | The last name of the customer, required | string |
Customer email address, required Note: Zero Hash will validate that the email is a correctly formatted email, and that the value is unique per-platform |
string | |
phone_number | The phone number of the participant, conditionally required | string |
address_one | First line for the customer's address, required Note: PO Box addresses are not accepted |
string |
address_two | Second line for the customer’s address, e.g., apartment, unit, building etc., if applicable, optional | string |
city | The city customer resides in, required | string |
state | The ISO code of the state the customer resides in (e.g. NY for New York), required if country is "United States" Note: must be one of the supported states |
ISO code string |
zip | Zip code of the customer in the format <5digits> or <5digits>-<4digits> , e.g. 77777 or 77777-7777 , required if country is "United States" |
string |
country | The country the customer resides in, required Note: must be one of the supported countries |
string |
date_of_birth | Date of birth of the customer in the format YYYY-MM-DD , required |
string |
citizenship | The citizenship of the participant, e.g. "United States", required | string |
tax_id | The national ID of the participant, e.g. a social security number. Required if citizenship=United States. | string |
id_number_type | The type of ID document provided, required if citizenship is not United States Note: must be one of the supported ID types ID types |
string |
id_number | The ID number for the customer, required if citizenship is not United States |
string |
non_us_other_type | This is required if you select non_us_other for the id_number_type - a freeform string to describe the ID type |
string |
id_issuing_authority | The issuing authority for the ID, if available, optional | string |
risk_rating | The risk-rating associated with the customer, conditionally required for certain platforms | string (low, medium, high) |
kyc | Whether the participant passed or failed KYC by vendor, required | string (pass, fail) |
kyc_timestamp | The UNIX timestamp (in milliseconds) when KYC was passed, required | timestamp |
sanction_screening | Whether the participant passed sanctions checks, required | string (pass, fail) |
sanction_screening_timestamp | The UNIX timestamp (in milliseconds) when sanction screening was passed, required | timestamp |
idv | Whether the participant passed or failed ID verification, optional | string (pass, fail) |
liveness_check | Whether the participant passed or failed a liveness check, optional | string (pass, fail) |
signed_timestamp | The UNIX timestamp (in milliseconds) when the Zero Hash Services Agreement was accepted by the participant | timestamp |
metadata | Can be used to submit any additional unstructured metadata | object |
Additional fields in response:
Parameter | Description | Type |
---|---|---|
platform_code | The unique identifier for the Platform onto which the customer has been created | string |
participant_code | The Zero Hash identifier for the new customer Note: this value is key to enable you to submit trades and check account balances for this customer |
string |
Possible Responses:
Status Code | Description |
---|---|
200 OK | The customer was successfully created. Note: the request is idempotent only IF therequest_id and payload is the same as previously submitted |
400 Bad Request | The request is invalid, OR the payload is the same as a previously submitted request, but the request_id is different, OR, the request_id is the same as a previously submitted request, but the payload is different |
Supported Regions
Zero Hash operates in a wide range of supported regions. For more information, please contact us to learn more. Please refer to our disclosures page for more information on regional regulation. Specifically, you can see a list of disclosures pertaining to certain states in which Zero Hash has licensing here.
ID Types
Valid options are:
us_drivers_license
us_passport
us_passport_card
us_permanent_resident_card
us_border_crossing_card
us_alien_card
us_id_card
non_us_passport
non_us_other
PATCH /participants/customers/:participantCode
const patchParticipantCustomer = () => {
const body = {
request_id: '7fbab305-2679-4279-808b-9b7a63a55c85',
first_name: 'John',
last_name: 'Smith',
address_one: '1 Main St.',
address_two: 'Suite 1000',
country: 'United States',
state: 'IL',
city: 'Chicago',
zip: '12345',
email: 'email-example@mail.com',
id_number_type: 'ssn',
id_number: '123456789',
platform_updated_at: 1603378501286
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'PATCH' + '/participants/customers/XXXXXX' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/customers/XXXXXX`,
options
)
}
resp = make_seed_request('PATCH', '/participants/customers/XXXXXX', {...})
Sample Request
{
"request_id": "7fbab305-2679-4279-808b-9b7a63a55c85",
"first_name": "John",
"last_name": "Smith",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"country": "United States",
"state": "IL",
"city": "Chicago",
"zip": "12345",
"email": "email-example@mail.com",
"id_number_type": "ssn",
"id_number": "123456789",
"platform_updated_at": 1603378501286
}
Sample Response
{
"message": {
"first_name": "John",
"last_name": "Smith",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"country": "United States",
"state": "IL",
"city": "Chicago",
"zip": "12345",
"email": "email-example@mail.com",
"date_of_birth": "1983-08-25",
"id_number_type": "ssn",
"id_number": "123456789",
"non_us_other_type": "",
"id_issuing_authority": "",
"signed_timestamp": 1603378501287,
"risk_rating": "",
"platform_code": "ABC123",
"participant_code": "XYZ456",
"platform_updated_at": 1603378501286
}
}
This endpoint enables you to update information that’s been validated with your customers. When making certain updates, groups of data must be sent together. If the data is not represented below, it’s not updatable. You can update more than one group of data at one time.
Request body:
Type of update | Parameter | Description | Type |
---|---|---|---|
platform_updated_at | The UNIX timestamp in milliseconds of when your customer updated their information with you and you approved that update. Only one timestamp should be sent per call (i.e. if you update name and address at the same time, there should be one timestamp, not one timestamp for name and one timestamp for address) | number | |
Name (e.g. customer gets married and changes their last name) | |||
first_name | The first name of the customer, required | string | |
last_name | The last name of the customer, required | string | |
Address (e.g. customer moves) | |||
address_one | First line for the customer's address, required Note: PO Box addresses are not accepted |
string | |
address_two | Second line for the customer’s address, e.g., apartment, unit, building etc., if applicable, optional | string | |
country | The country the customer resides in, required Note: must be one of the supported countries |
string | |
state | The ISO code of the state the customer resides in (e.g. NY for New York), required if country is "United States" Note: must be one of the supported states |
ISO code string | |
city | The city customer resides in, required | string | |
zip | Zip code of the customer in the format<5digits> or <5digits>-<4digits> , e.g. 77777 or 77777-7777 , required if country is "United States" |
string | |
Email (e.g. customer changes from a work to a personal email) | |||
Customer email address, required Note: Zero Hash will validate that the email is a correctly formatted email, and that the value is unique per-platform |
string | ||
Identification (e.g. customer updates their ID on file with you) | |||
id_number_type | The type of ID document provided, required Note: must be one of the supported ID types |
string | |
id_number | The ID number of the customer, required | string | |
Citizen records (only available where entries are currently blank) | |||
citizenship | If the participant does not have a defined citizenship, this can be added, one-time | string | |
tax_id | If the participant was created, but now requires a tax_id, this can be added, one-time | string | |
Contact information | |||
phone_number | Mobile phone number of the participant | string |
Additional fields in response:
Parameter | Description | Type |
---|---|---|
platform_code | The unique identifier for the Platform onto which the customer has been created | string |
participant_code | The Zero Hash identifier for the new customer Note: this value is key to enable you to submit trades and check account balances for this customer |
string |
platform_updated_at | The timestamp of when a customer updated their information with your platform | number |
Possible Responses:
Status Code | Description |
---|---|
200 OK | The customer was successfully created. Note: the request is idempotent only IF therequest_id and payload is the same as previously submitted |
400 Bad Request | The request is invalid, OR the payload is the*same* as a previously submitted request, but the request_id is different, OR, the request_id is the same as a previously submitted request, but the payload is different |
POST /participants/customers/:participantCode/lock
const postParticipantCustomerLock = () => {
const body = {
reason_code: "compliance_issue",
notes: "confirmed fraud"
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/participants/customers/XXXXXX/lock' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/customers/XXXXXX/lock`,
options
)
}
resp = make_seed_request('POST', '/participants/customers/XXXXXX/lock', {...})
Sample Request
{
"reason_code": "compliance_issue",
"notes": "confirmed fraud"
}
Sample Response
OK
When platforms terminate a customer, they may alert Zero Hash through this endpoint. Hitting this endpoint will lock the user so the Zero Hash compliance team can conduct investigations.
Please note: Platforms cannot update the participant status further - once the participant is locked, the Zero Hash compliance team must take action and will potentially request supporting evidence from the platform.
If making a request for a participant who has been locked or disabled, platforms will receive an error message of Participant [participant_code] is not allowed to transact
Request body:
Parameter | Description | Type |
---|---|---|
reason_code | compliance_issue or user_request , required |
string |
notes | Additional details on the lock, which can drastically speed up investigations on the Zero Hash side | string |
Possible Responses:
Status Code | Description |
---|---|
200 OK | The customer was successfully created. Note: the request is idempotent only IF therequest_id and payload is the same as previously submitted |
400 Bad Request | The request is invalid or failed |
Custodian Relationship Types
Valid options are:
parent
legal_guardian
POST /participants/customers/minor
const postParticipantMinor = () => {
const body = {
first_name: 'John',
last_name: 'Smith',
email: 'test@example.com',
address_one: '1 Main St.',
address_two: 'Chicago',
country: 'United States',
city: 'Chicago',
zip: '12345',
state: 'IL',
date_of_birth: '2018-09-02',
id_number_type: 'ssn',
id_number: '123456789',
non_us_other_type: null,
id_issuing_authority: null,
utma_signed_timestamp: 1603378501286,
custodian_participant_code: 'CAST01',
custodian_relationship: 'parent',
metadata: {}
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/participants/customers/minor' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/customers/minor`,
options
)
}
resp = make_seed_request('POST', '/participants/customers/minor', {})
Sample Request
{
"first_name": "John",
"last_name": "Smith",
"email": "test@example.com",
"address_one": "1 Main St.",
"address_two": "Chicago",
"country": "United States",
"city": "Chicago",
"zip": "12345",
"state": "IL",
"date_of_birth": "2018-09-02",
"id_number_type": "ssn",
"id_number": "123456789",
"non_us_other_type": null,
"id_issuing_authority": null,
"utma_signed_timestamp": 1603378501286,
"custodian_participant_code": "CAST01",
"custodian_relationship": "parent",
"metadata": {}
}
Sample Response
{
"message": {
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"address_one": "string",
"address_two": "string",
"country": "string",
"city": "string",
"zip": "string",
"state": "string",
"date_of_birth": "string",
"id_number_type": "ssn",
"id_number": "string",
"non_us_other_type": "string",
"id_issuing_authority": "string",
"utma_signed_timestamp": 0,
"custodian_participant_code": "string",
"participant_code": "string",
"platform_code": "string",
"custodian_relationship": "string",
"metadata": {}
}
}
Submits a minor and links it to a custodian. Used in the context of the UTMA product.
Request body:
Parameter | Description | Type |
---|---|---|
first_name | The first name of the customer, required | string |
last_name | The last name of the customer, required | string |
Customer email address, required Note: Zero Hash will validate that the email is a correctly formatted email, and that the value is unique per-platform |
string | |
address_one | First line for the customer's address, required Note: PO Box addresses are not accepted |
string |
address_two | Second line for the customer’s address, e.g., apartment, unit, building etc., if applicable, optional | string |
city | The city customer resides in, required | string |
state | The ISO code of the state the customer resides in (e.g. NY for New York), required if country is "United States" Note: must be one of the supported states |
ISO code string |
zip | Zip code of the customer in the format <5digits> or <5digits>-<4digits> , e.g. 77777 or 77777-7777 , required if country is "United States" |
string |
country | The country the customer resides in, required Note: must be one of the supported countries |
string |
date_of_birth | Date of birth of the customer in the format YYYY-MM-DD , required |
string |
id_number_type | The type of ID document provided, required Note: must be one of the supported ID types |
string |
id_number | The ID number for the customer, required | string |
non_us_other_type | This is required if you select non_us_other for the id_number_type - a freeform string to describe the ID type |
string |
id_issuing_authority | The issuing authority for the ID, if available, optional | string |
utma_signed_timestamp | The UNIX timestamp (in milliseconds) when the User Agreement UTMA Addendum was accepted by the custodian | timestamp |
custodian_participant_code | The already-submitted participant code of the associated custodian | object |
custodian_relationship | The type of custodian provided. if the field is filled, must be one of the supported custodian relationship | string |
metadata | Can be used to submit any additional unstructed metadata | object |
Additional fields in response:
Parameter | Description | Type |
---|---|---|
platform_code | The unique identifier for the Platform onto which the customer has been created | string |
participant_code | The Zero Hash identifier for the new customer Note: this value is key to enable you to submit trades and check account balances for this customer |
string |
Supported Regions
Zero Hash operates in a wide range of supported regions. For more information, please contact us to learn more. Please refer to our disclosures page for more information on regional regulation. Specifically, you can see a list of disclosures pertaining to certain states in which Zero Hash has licensing here.
ID Types
Valid options are:
ssn
us_drivers_license
us_passport
us_passport_card
us_permanent_resident_card
us_border_crossing_card
us_alien_card
us_id_card
non_us_passport
non_us_other
POST /participants/documents
const postParticipantDocument = (filepath) => {
const document = fs.readFileSync(filepath).toString('base64')
const body = {
document,
mime: 'pdf',
file_name: 'supporting_document.pdf',
participant_code: 'ABC123'
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/participants/documents' + JSON.stringify(
{})
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
const fileHash = crypto
.createHash('sha256')
.update(body.document)
.digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase',
'X-SCX-FILE-HASH': fileHash
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/documents`,
options
)
}
with open(filepath, 'rb') as document:
resp = make_seed_request('POST', '/participants/documents', {
'document': base64.b64encode(document.read()),
'mime': 'pdf',
'file_name': 'supporting_document.pdf',
'participant_code': 'ABC123'
})
Sample Request
{
"document": "aGVsbG8gd29ybGQ=",
"mime": "pdf",
"file_name": "supporting_document.pdf",
"participant_code": "ABC123"
}
Sample Response
{
"message": {
"state": "Success",
"file_name": "supporting_document.pdf",
"created_at": 1572899177383
}
}
Submits a document on behalf of you or a customer if you operate a platform on Zero Hash. In order to Authenticate you will need to do the following:
- Set your X-SCX-FILE-HASH header to the sha256 hash (in a byte array) of your file contents and encode this data to base64 string.
- Make sure to use
{}
as your body when signing your request. If you use your actual request body to sign you will receive andInvalid Client Signature
. - Ensure that your file is not larger than 10mb.
- Remember to base 64 encode your file before sending it to us.
Request body:
Parameter | Description | Type |
---|---|---|
document | base 64 encoded file that you wish to upload (10mb limit) | binary |
mime | The MIME type of the file you are uploading | string |
file_name | The name of the document that you are uploading | string |
participant_code | Your participant code, or the participant_code of the customer on behalf of whom you are uploading the document | string |
POST /participants/entity/new
const postEntity = () => {
const body = {
request_id: "98957700-c08c-4c4c-9c6b-dcc70d3da90c",
platform_code:"PLAT01",
entity_name:"Entity Name",
legal_name:"Legal Name",
contact_number:"15553765432",
website:"www.example.com",
date_established:"2000-01-15",
entity_type:"llc",
address_one:"1 Main St.",
address_two:"Suite 1000",
city:"Chicago",
state_or_province:"IL",
postal_code:"12345",
country:"United States",
tax_id:"883987654",
id_issuing_authority:"United States",
risk_rating:"low",
risk_vendor:"passbase",
sanction_screening:"pass",
sanction_screening_timestamp:1677252628000,
metadata:{},
signed_timestamp:1677252629000,
submitter_email:"example@zerohash.com",
control_persons:[
{
name:"Joe Doe",
email:"joe.doe@test.com",
address_one:"1 South St.",
address_two:"Suite 2000",
city:"Chicago",
state_or_province:"IL",
postal_code:"12345",
country:"United States",
date_of_birth:"1979-01-30",
citizenship:"United States",
tax_id:"123456789",
id_number_type:"us_passport",
id_number:"332211200",
id_issuing_authority:"United States",
sanction_screening:"pass",
sanction_screening_timestamp:1677252628000,
kyc:"pass",
kyc_timestamp:1603378501285,
control_person:1
},
{
name:"Joe Doe Jr",
email:"joedoejr@test.com",
address_one:"1 South St.",
address_two:"Suite 2000",
city:"Chicago",
state_or_province:"IL",
postal_code:"12345",
country:"United States",
date_of_birth:"1979-01-30",
citizenship:"United States",
tax_id:"123456779",
id_number_type:"us_passport",
id_number:"332511100",
id_issuing_authority:"United States",
sanction_screening:"pass",
sanction_screening_timestamp:1677252628000,
kyc:"pass",
kyc_timestamp:1603378501285,
control_person:1
}
],
beneficial_owners:[
{
name:"Jane Doe",
beneficial_owner:2,
email:"jane.doe@test.com",
address_one:"1 North St.",
address_two:"Suite 3000",
city:"Chicago",
state_or_province:"IL",
postal_code:"12345",
country:"United States",
date_of_birth:"1980-01-30",
citizenship:"United States",
tax_id:"013345678",
id_number_type:"us_drivers_license",
id_number:"P11122223333",
id_issuing_authority:"United States",
sanction_screening:"pass",
sanction_screening_timestamp:1677252628000
kyc:"pass",
kyc_timestamp:1603378501285
},
{
name:"Jane Doe Jr",
beneficial_owner:1,
email:"janedoejr@test.com",
address_one:"1 North St.",
address_two:"Suite 3000",
city:"Chicago",
state_or_province:"IL",
postal_code:"12345",
country:"United States",
date_of_birth:"1980-01-30",
citizenship:"United States",
tax_id:"012345578",
id_number_type:"us_drivers_license",
id_number:"P11122243333",
id_issuing_authority:"United States",
sanction_screening:"pass",
sanction_screening_timestamp:1677252628000,
kyc:"pass",
kyc_timestamp:1603378501285
}
]
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/participants/entity/new' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/entity/new`,
options
)
}
resp = make_seed_request('POST', '/participants/entity/new', {})
Sample Request
{
"request_id": "98957700-c08c-4c4c-9c6b-dcc70d3da90c",
"platform_code":"PLAT01",
"entity_name":"Entity Name",
"legal_name":"Legal Name",
"contact_number":"15553765432",
"website":"www.example.com",
"date_established":"2000-01-15",
"entity_type":"llc",
"address_one":"1 Main St.",
"address_two":"Suite 1000",
"city":"Chicago",
"state_or_province":"IL",
"postal_code":"12345",
"country":"United States",
"tax_id":"883987654",
"id_issuing_authority":"United States",
"risk_rating":"low",
"risk_vendor":"passbase",
"sanction_screening":"pass",
"sanction_screening_timestamp":1677252628000,
"metadata":{
},
"signed_timestamp":1677252629000,
"submitter_email":"example@zerohash.com",
"control_persons":[
{
"name":"Joe Doe",
"email":"joe.doe@test.com",
"address_one":"1 South St.",
"address_two":"Suite 2000",
"city":"Chicago",
"state_or_province":"IL",
"postal_code":"12345",
"country":"United States",
"date_of_birth":"1979-01-30",
"citizenship":"United States",
"tax_id":"123456789",
"id_number_type":"us_passport",
"id_number":"332211200",
"id_issuing_authority":"United States",
"sanction_screening":"pass",
"sanction_screening_timestamp":1677252628000,
"kyc":"pass",
"kyc_timestamp":1603378501285,
"control_person":1
},
{
"name":"Joe Doe Jr",
"email":"joedoejr@test.com",
"address_one":"1 South St.",
"address_two":"Suite 2000",
"city":"Chicago",
"state_or_province":"IL",
"postal_code":"12345",
"country":"United States",
"date_of_birth":"1979-01-30",
"citizenship":"United States",
"tax_id":"123456779",
"id_number_type":"us_passport",
"id_number":"332511100",
"id_issuing_authority":"United States",
"sanction_screening":"pass",
"sanction_screening_timestamp":1677252628000,
"kyc":"pass",
"kyc_timestamp":1603378501285,
"control_person":2
}
],
"beneficial_owners":[
{
"name":"Jane Doe",
"beneficial_owner":2,
"email":"jane.doe@test.com",
"address_one":"1 North St.",
"address_two":"Suite 3000",
"city":"Chicago",
"state_or_province":"IL",
"postal_code":"12345",
"country":"United States",
"date_of_birth":"1980-01-30",
"citizenship":"United States",
"tax_id":"013345678",
"id_number_type":"us_drivers_license",
"id_number":"P11122223333",
"id_issuing_authority":"United States",
"sanction_screening":"pass",
"sanction_screening_timestamp":1677252628000,
"kyc":"pass",
"kyc_timestamp":1603378501285,
"role":"Example Role"
},
{
"name":"Jane Doe Jr",
"beneficial_owner":1,
"email":"janedoejr@test.com",
"address_one":"1 North St.",
"address_two":"Suite 3000",
"city":"Chicago",
"state_or_province":"IL",
"postal_code":"12345",
"country":"United States",
"date_of_birth":"1980-01-30",
"citizenship":"United States",
"tax_id":"012345578",
"id_number_type":"us_drivers_license",
"id_number":"P11122243333",
"id_issuing_authority":"United States",
"sanction_screening":"pass",
"sanction_screening_timestamp":1677252628000,
"kyc":"pass",
"kyc_timestamp":1603378501285
}
]
}
Sample Response
{
"message": {
"platform_code": "PLAT01",
"participant_code": "PART01",
"status": "submitted",
"entity_name": "Entity Name",
"legal_name": "Legal Name",
"address_one": "1 Main St.",
"address_two": "Suite 1000",
"country": "United States",
"state_or_province": "IL",
"city": "Chicago",
"postal_code": "12345",
"date_established": "2000-01-15",
"risk_rating": "low",
"risk_vendor": "passbase",
"entity_type": "llc",
"metadata": {},
"signed_timestamp": 1677252629000,
"tax_id": "883987654",
"contact_number": "15553765432",
"website": "www.example.com",
"id_issuing_authority": "United States",
"sanction_screening": "pass",
"sanction_screening_timestamp": 1677252628000,
"submitter_email": "example@zerohash.com",
"beneficial_owners": [
{
"user_code": "U-USERCO",
"beneficial_owner": 2,
"name": "Jane Doe",
"email": "jane.doe@test.com",
"address_one": "1 North St.",
"address_two": "Suite 3000",
"city": "Chicago",
"state_or_province": "IL",
"postal_code": "12345",
"country": "United States",
"date_of_birth": "1980-01-30",
"citizenship": "United States",
"tax_id": "013345678",
"id_number_type": "us_drivers_license",
"id_number": "P11122223333",
"id_issuing_authority": "United States",
"sanction_screening": "pass",
"sanction_screening_timestamp": 1677252628000,
"kyc": "pass",
"kyc_timestamp": 1603378501285,
"role":"Example Role"
},
{
"user_code": "U-USERC1",
"beneficial_owner": 1,
"name": "Jane Doe Jr",
"email": "janedoejr@test.com",
"address_one": "1 North St.",
"address_two": "Suite 3000",
"city": "Chicago",
"state_or_province": "IL",
"postal_code": "12345",
"country": "United States",
"date_of_birth": "1980-01-30",
"citizenship": "United States",
"tax_id": "012345578",
"id_number_type": "us_drivers_license",
"id_number": "P11122243333",
"id_issuing_authority": "United States",
"sanction_screening": "pass",
"sanction_screening_timestamp": 1677252628000,
"kyc": "pass",
"kyc_timestamp": 1603378501285
}
],
"control_persons": [
{
"user_code": "U-USERC2",
"name": "Joe Doe",
"email": "joe.doe@test.com",
"address_one": "1 South St.",
"address_two": "Suite 2000",
"city": "Chicago",
"state_or_province": "IL",
"postal_code": "12345",
"country": "United States",
"date_of_birth": "1979-01-30",
"citizenship": "United States",
"tax_id": "123456789",
"id_number_type": "us_passport",
"id_number": "332211200",
"id_issuing_authority": "United States",
"sanction_screening": "pass",
"sanction_screening_timestamp": 1677252628000,
"kyc": "pass",
"kyc_timestamp": 1603378501285,
"control_person": 1
},
{
"user_code": "U-USERC3",
"name": "Joe Doe Jr",
"email": "joedoejr@test.com",
"address_one": "1 South St.",
"address_two": "Suite 2000",
"city": "Chicago",
"state_or_province": "IL",
"postal_code": "12345",
"country": "United States",
"date_of_birth": "1979-01-30",
"citizenship": "United States",
"tax_id": "123456779",
"id_number_type": "us_passport",
"id_number": "332511100",
"id_issuing_authority": "United States",
"sanction_screening": "pass",
"sanction_screening_timestamp": 1677252628000,
"kyc": "pass",
"kyc_timestamp": 1603378501285,
"control_person": 2
}
]
}
}
When posting new entities, platforms are also required to post documents. See POST /participants/entity/documents for information.
Request body:
Parameter | Description | Requirement | Input |
---|---|---|---|
request_id | A universally unique identifier (UUID) for this request Note: To ensure idempotence, it is recommended to include this parameter |
optional, but highly recommended | string |
platform_code | Zero Hash platform code of the submitting platform | required | string |
BUSINESS INFO | |||
entity_name | Name of the business | required | string |
legal_name | Registered legal name of the entity. This should not be a DBA or DBA equivalent | required | string |
contact_number | Phone number of the business | required | string |
website | Business website | required | string |
date_established | Date the business was established. This should reflect government registration for the entity | required | YYYY-MM-DD |
entity_type | The type of business that is onboarding, must be one of the supported Entity Types | required | string |
address_one | Address of the business, no P.O. Boxes | required | string |
address_two | Address of the registered business continued, no P.O. Boxes | optional | string |
city | City of the business | required | string |
state_or_province | State of the business | required (for US address) | string |
postal_code | Postal, or zip code, of the business, in the format <5digits> or <5digits>-<4digits>, e.g. 77777 or 77777-7777 | required | string |
country | Country of the business. Note: must be one of the supported countries | required | string |
tax_id | Tax identifier of the business (e.g. EIN in United States) | required | string |
id_issuing_authority | Country that issued the tax identifier (e.g. “United States”) | required | string |
risk_rating | Risk assessed by the platform’s vendor | required | low, medium, high |
sanction_screening | Result of the business sanctions screen | required | pass, fail |
sanction_screening_timestamp | The time the sanctions screen was done | required | UNIX timestamp in milliseconds |
metadata | Additional unstructured data | optional | object |
signed_timestamp | The time at which the business accepted Zero Hash services agreements | required | UNIX timestamp in milliseconds |
CONTROL PERSON(S) | submit as many as necessary, for each director, officer, member, or partner, etc. | ||
name | Full name of the control person | required | string |
Email address of control person | required | string | |
address_one | Address of the control person, no P.O. Boxes | required | string |
address_two | Address of the control person continued, no P.O. Boxes | optional | string |
city | City of the control person | required | string |
state_or_province | State of the control person | required (for US address) | string |
postal_code | Postal, or zip code, of the control person, in the format <5digits> or <5digits>-<4digits>, e.g. 77777 or 77777-7777 | required | string |
country | Country of the control person | required | string |
date_of_birth | Birth date of the control person | required | YYYY-MM-DD |
citizenship | Citizenship of the control person (e.g. “United States”) | required | string |
tax_id | Tax identifier of the control person (e.g. 9-digit SSN in United States) | conditionally required if citizenship = “United States” | string |
id_number_type | Type of ID document provided. Note: must be one of the supported ID Number Types | required | string |
id_number | ID number of the ID document provided | required | string |
id_issuing_authority | Country that issued the ID, if available (e.g. “United States”) | optional | string |
sanction_screening | Result of the control person’s sanctions screen | required | pass, fail |
sanction_screening_timestamp | The time the control person’s sanctions screen was done | required | UNIX timestamp in milliseconds |
kyc | Whether the participant passed or failed KYC by vendor | required | pass, fail |
kyc_timestamp | The UNIX timestamp (in milliseconds) when KYC was passed | required | timestamp |
control_person | Designation of what percent of the business the person controls. Unknown = 0; Less than 10% = 1; Greater than or equal to 10% but less than 25% = 2; Greater than or equal to 25% = 3 | required | number |
BENEFICIAL OWNER(S) | Individual(s) who controls ≥25%, submit as many as necessary. If no Beneficial Owner(s), this section can be omitted. Zero Hash only requires inclusion of BOs who hold ≥25%, but those who hold 10-24% can be disclosed for compliance due diligence at the platform’s discretion. | ||
name | Full name of the beneficial owner | required | string |
beneficial_owner | Designation of what percent of the business the person owns. Unknown = 0; Greater than or equal to 10% but less than 25% = 1; Greater than or equal to 25% = 2 | required | number |
Email address of beneficial owner | required | string | |
address_one | Address of the beneficial owner, no P.O. Boxes | required | string |
address_two | Address of the beneficial owner continued, no P.O. Boxes | optional | string |
city | City of the beneficial owner | required | string |
state_or_province | State of the beneficial owner | required | string |
postal_code | Postal, or zip code, of the beneficial owner, in the format <5digits> or <5digits>-<4digits>, e.g. 77777 or 77777-7777 | required | string |
country | Country of the beneficial owner | required | string |
date_of_birth | Birth date of the beneficial owner | required | YYYY-MM-DD |
citizenship | Citizenship of the beneficial owner (e.g. “United States”) | required | string |
tax_id | Tax identifier of the beneficial owner (e.g. 9-digit SSN in United States) | conditionally required if citizenship = “United States” | string |
id_number_type | Type of ID document provided. Note: must be one of the supported ID Number Types | required | string |
id_number | ID number of the ID document provided | required | string |
id_issuing_authority | Country that issued the ID, if available (e.g. “United States”) | optional | string |
sanction_screening | Result of the beneficial owner’s sanctions screen | required | pass, fail |
sanction_screening_timestamp | The time the beneficial owner’s sanctions screen was done | required | UNIX timestamp in milliseconds |
kyc | Whether the participant passed or failed KYC by vendor | required | pass, fail |
kyc_timestamp | The UNIX timestamp (in milliseconds) when KYC was passed | required | timestamp |
role | The role of the benificial owner | optonal | string |
SUBMITTER | |||
submitter_email | Email of the person who completed the KYC application and agreed to terms | required | string |
Additional fields in response:
Parameter | Description | Type |
---|---|---|
participant_code | The Zero Hash identifier for the new customer Note: this value is key to enable you to submit trades and check account balances for this customer |
string |
status | When a successful POST has occurred, the Zero Hash response includes the status of the business participant, which indicates whether or not the business participant can immediately make requests |
|
user_code | Zero Hash identifier for the Control Person(s) or Beneficial Owner(s). One code returned per person. | string |
Possible Responses:
Status Code | Description |
---|---|
200 OK | The participant was successfully created. See status to understand whether or not that participant can immediately transact. |
400 Bad Request | The request was invalid, or the request was missing required fields. |
Supported Regions
Zero Hash operates in a wide range of supported regions. For more information, please contact us to learn more. Please refer to our disclosures page for more information on regional regulation. Specifically, you can see a list of disclosures pertaining to certain states in which Zero Hash has licensing here.
Entity Types
Valid options are:
corp
llc
partnership
sole_proprietorship
other*
*If posting a non-profit organization, use “other” and submit <“entity_type”: “non-profit”> in the business info metadata.
ID Number Types
Valid options are:
us_drivers_license
us_passport
us_passport_card
us_permanent_resident_card
us_border_crossing_card
us_alien_card
us_id_card
non_us_passport
non_us_other
POST /participants/entity/documents
const postEntityDocument = (filepath) => {
const document = fs.readFileSync(filepath).toString('base64')
const body = {
document,
mime: 'pdf',
document_type: "proof_of_address",
file_name: "proof_of_address.pdf",
participant_code: 'ABC123'
}
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/participants/entity/documents' + JSON.stringify(
{})
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
const fileHash = crypto
.createHash('sha256')
.update(body.document)
.digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase',
'X-SCX-FILE-HASH': fileHash
}
const options = {
headers,
body,
json: true
}
return request.post(
`https://api.zerohash.com/participants/entity/documents`,
options
)
}
with open(filepath, 'rb') as document:
resp = make_seed_request('POST', '/participants/entity/documents', {
'document': base64.b64encode(document.read()),
'mime': 'pdf',
"document_type": "proof_of_address",
"file_name": "proof_of_address.pdf",
'participant_code': 'ABC123'
})
Sample Request - Business documents
{
"document": "aGVsbG8gd29ybGQ=",
"mime": "pdf",
"document_type": "proof_of_address",
"file_name": "proof_of_address.pdf",
"participant_code": "ABC123"
}
Sample Response - Business documents
{
"message": {
"state": "Success",
"file_name": "proof_of_address.pdf",
"created_at": 1572899177383
}
}
Sample Request - Control Person / Beneficial Owner documents
{
"document": "aGVsbG8gd29ybGQ=",
"mime": "jpg",
"document_type": "us_passport"
"file_name": "jane_doe_passport.jpg",
"user_code": "XYZ789"
}
Sample Response - Control Person / Beneficial Owner documents
{
"message": {
"state": "Success",
"file_name": "jane_doe_passport.jpg",
"created_at": 1572899177383
}
}
Posting a business participant requires that specific documentation is passed to Zero Hash. One document can be submitted per call. In order to Authenticate you will need to do the following:
- Set your X-SCX-FILE-HASH header to the sha256 hash (in a byte array) of your file contents and encode this data to base64 string.
- Make sure to use
{}
as your body when signing your request. If you use your actual request body to sign you will receive andInvalid Client Signature
. - Ensure that your file is not larger than 10mb.
- Remember to base 64 encode your file before sending it to us.
Document requirements
Document requirements are validated and depend on the entity_type passed in POST /participants/entity/new.
Entity type | Documents required (*if applicable) |
---|---|
Sole proprietorship |
|
Partnership |
|
LLC |
|
Corporation |
|
Other | If submitting a non-profit organization, Association/Organization agreement and/or by_laws, proof_of_address, proof_of_non_profit_status, + valid ID types for Control Person(s) are required. |
Request body:
Parameter | Description | Requirement | Input |
---|---|---|---|
document | base 64 encoded file that you wish to upload (10mb limit) | required | binary |
mime | The MIME type of the file you are uploading | required | string |
document_type | The type of document provided. Note: must be one of the supported Document types |
required | string |
file_name | The name of the document that you are uploading | required | string |
participant_code OR user_code | Zero Hash designated participant code of the business participant created in |
required | string |
Document types
Valid options are:
articles_of_incorporation
articles_of_organization
business_license
business_name_filing_document
by_laws
articles_of_organization
certificate_of_good_standing
certificate_of_incorporation
certificate_of_organization
operating_agreement
partnership_agreeement
proof_of_address
unknown
valid
ID typesfor Control Person(s)
Liquidity
GET /liquidity/rfq
const getQuote = () => {
const body = '{}'
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/liquidity/rfq?underlying=BTC"ed_currency=USD&side=buy&quantity=1' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(`https://api.zerohash.com/liquidity/rfq?underlying=BTC"ed_currency=USD&side=buy&quantity=1`, options)
}
accounts = make_seed_request('GET', '/liquidity/rfq', {})
Sample Response
{
"request_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3",
"participant_code": "CUST01",
"quoted_currency": "USD",
"side": "BUY",
"quantity": "1",
"price": "11430.90",
"quote_id": "5cd07738b861c31e3bd61467BTC1Buy1568311644602",
"expire_ts": 1568311649602,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "20XRLH",
"account_group": "WRD1K0",
"account_label": "general"
},
"network_fee_notional": "1",
"network_fee_quantity": "1",
"main_quote_id": "c3a7e3a6-a911-43e8-b3bb-2b562c2d8c28",
"total_notional": "11.00",
"underlying": "ETH"
}
Returns a quote to buy or sell a certain asset, in return for another asset. See one-pager here for more details.
Query parameters include:
side
(required) the side of the quotebuy
orsell
)underlying
(required) the underlying asset for the quotequoted_currency
(required) the quoted asset for the quotequantity
(optional) The amount of theunderlying
currency (eitherquantity
ortotal
must be provided)total
(optional) the desired amount of thequoted_currency
for the quote (eitherquantity
ortotal
must be provided)participant_code
(optional) the participant that is requesting to buy/sell. Can be the platform's code or the customer's.account_label
(optional) the account label associated with the account.
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the RFQ | string |
participant_code | The identifier of the participant making the quote request | string |
quoted_currency | The asset code for the quoted currency, e.g. USD |
string |
side | The participant side of the quote - buy or sell |
string |
quantity | The amount of the quoted currency | string |
price | The cost per unit of underlying currency | string |
quote_id | The identifier for the quote Note: this is required to execute the quote |
string |
expire_ts | Timestamp when the quote will expire | timestamp |
account_group | The group that the account is a part of | string |
account_label | The account label associated with the account | string |
obo_participant | on behalf of participant is the details of the participant benefiting the trade if not the submitter | object |
network_fee_notional | fee notional in the currency quoted on the RFQ | string |
network_fee_quantity | fee quantity in the underlying asset | string |
main_quote_id | the quote ID for the liquidity provider for the quote itself | string |
total_notional | The calculation: (price * quantity ) + (network_fee_notional * network_fee_quantity ) |
string |
underlying | The asset code for the underlying currency, e.g. BTC |
string |
POST /liquidity/execute
const executeQuote = (id: string) => {
const body = '{ "quote_id":' + id + '}'
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/liquidity/execute' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/liquidity/execute`, options)
}
accounts = make_seed_request('POST', '/liquidity/execute', {"quote_id": id})
Sample Response
{
"request_id": "14f8ebb8-7530-4aa4-bef9-9d73d56313f3",
"quote": {
"request_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3",
"participant_code": "CUST01",
"quoted_currency": "USD",
"side": "BUY",
"quantity": "1",
"price": "11430.90",
"quote_id": "5cd07738b861c31e3bd61467BTC1Buy1568311644602",
"expire_ts": 1568311649602,
"account_group": "GRP001",
"account_label": "general",
"obo_participant": {
"participant_code": "20XRLH",
"account_group": "WRD1K0",
"account_label": "general"
},
"network_fee_notional": "1",
"network_fee_quantity": "1",
"total_notional": "2.00",
"underlying": "BTC",
"asset_cost_notional": "2.00"
},
"trade_id": "ba97133e-ab15-4c86-86c1-86671b8420bc",
"status": "Completed",
"ach_details": {
"inbound_reference_id": "ref-id",
},
"payment_amount": "10"
}
Executes the quote identified by quote_id. The completed trade is submitted to settlement via the 00SCXM
platform. Platforms may now use the funding_details
sub-object to trigger Zero Hash to create an ACH transaction associated with a trade. Speak with Zero Hash support for more details.
Body parameters include:
quote_id
(required) the identifier of the quote to execute, which is provided in response to aGET /liquidity/rfq
requestfunding_details
(Only applicable if utilizing Zero Hash's ACH Product)inbound_reference_id
(required) a Platform generated string value that Zero Hash can use to reconcile inbound ACH transactions.
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the RFQ. | string |
quote{} | The quote object that was executed. | quote |
trade_id | The unique identifier assigned to the trade, which is the same trade_id as found in a GET /trades requestNote: the quote_id will be saved as the client_trade_id . |
string |
status | The status of the trade, e.g. Completed . |
string |
payment_amount | The final amount of the ACH transaction that will go out into the network. When executing a BUY this is the trade amount plus the bank_fee , for a SELL this is the trade amount minus the bank_fee . |
string |
Convert and Withdraw
GET /convert_withdraw/rfq
const getQuote = () => {
const body = '{}'
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/convert_withdraw/rfq?underlying=BTC"ed_currency=USD&side=buy&quantity=1&withdrawal_address=address&participant_code=TEST_USER' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.get(`https://api.zerohash.com/convert_withdraw/rfq?underlying=BTC"ed_currency=USD&side=buy&quantity=1&withdrawal_address=address&participant_code=TEST_USER`, options)
}
accounts = make_seed_request('GET', f'/convert_withdraw/rfq?underlying=ETH"ed_currency=USD&side=buy&quantity=0.001&withdrawal_address=address&participant_code=TEST_USER')
Sample Response
{
"message": {
"request_id": "82041737-db0d-417a-9702-b7e302ded74a",
"participant_code": "TEST_USER",
"quoted_currency": "USD",
"side": "buy",
"quantity": "0.001",
"price": "1644.4414765625",
"quote_id": "b666594f-0b6f-4979-b3d7-46d5727124f2",
"expire_ts": 1694119245469,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "TEST_USER",
"account_group": "TEST_USER",
"account_label": "general"
},
"network_fee_notional": "0.05",
"network_fee_quantity": "0.0000315000002268",
"total_notional": "1.69",
"underlying": "ETH",
"asset_cost_notional": "1.64"
}
}
Returns a quote for the asset purchase amount and also the network fee associated with an eminent withdrawal.
Query parameters include:
side
(required) the side of the quote, supported value:buy
underlying
(required) the underlying asset for the quotequoted_currency
(required) the quoted asset for the quotewithdrawal_address
(required) the on-chain address for the withdrawaldestination_tag
(optional) for tag-based assets, please provide the memo id/destination tag value in this field. For more information on when and how to populate this field, please refer hereno_destination_tag
(optional) the value should be true or false. For more information on when and how to populate this field, please refer here. Supported values aretrue
orfalse
quantity
(optional) The amount of theunderlying
currency (eitherquantity
ortotal
must be provided)total
(optional) the desired amount of thequoted_currency
for the quote (eitherquantity
ortotal
must be provided)participant_code
(optional) the participant that is requesting to buy/sell. Can be the platform's code or the customer's.fee_inclusive
(optional) only applicable for orders bytotal
. If true, the total_notional will be equal to that of thetotal
value specified, fees included.
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the RFQ | string |
participant_code | The identifier of the participant making the quote request | string |
quoted_currency | The asset code for the quoted currency, e.g. USD |
string |
side | The participant side of the quote - buy or sell |
string |
quantity | The amount of the quoted currency | string |
price | The cost per unit of underlying currency | string |
quote_id | The identifier for the quote Note: this is required to execute the quote |
string |
expire_ts | Timestamp when the quote will expire | timestamp |
account_group | The group that the account is a part of | string |
account_label | The account label associated with the account | string |
obo_participant | on behalf of participant is the details of the participant benefiting the trade if not the submitter | object |
network_fee_notional | fee notional in the currency quoted on the RFQ | string |
network_fee_quantity | fee quantity in the underlying asset | string |
total_notional | The calculation: (price * quantity ) + (network_fee_notional * network_fee_quantity ) |
string |
underlying | The asset code for the underlying currency, e.g. BTC |
string |
POST /convert_withdraw/execute
const executeQuote = (id: string) => {
const body = '{ "quote_id":' + id + '}'
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'GET' + '/convert_withdraw/execute' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/convert_withdraw/execute`, options)
}
accounts = make_seed_request('POST', '/convert_withdraw/execute', {"quote_id": id})
Sample Response
{
"message": {
"request_id": "fd4e6d89-8302-4138-8546-ded5d285e2b3",
"quote": {
"request_id": "82041737-db0d-417a-9702-b7e302ded74a",
"participant_code": "TEST_USER",
"quoted_currency": "USD",
"side": "buy",
"quantity": "0.001",
"price": "1644.4414765625",
"quote_id": "b666594f-0b6f-4979-b3d7-46d5727124f2",
"expire_ts": 1694119245469,
"account_group": "00SCXM",
"account_label": "general",
"obo_participant": {
"participant_code": "TEST_USER",
"account_group": "TEST_USER",
"account_label": "general"
},
"network_fee_notional": "0.05",
"network_fee_quantity": "0.0000315000002268",
"total_notional": "1.69",
"underlying": "ETH",
"asset_cost_notional": "1.64",
"transaction_timestamp": 1694119240807
},
"trade_id": "e5886d46-eceb-4f2b-b7d2-a599240e35ae",
"status": "Completed",
"trade_ids_list": [
"e5886d46-eceb-4f2b-b7d2-a599240e35ae"
],
"withdrawal_request_id": "53295c6a-79f4-4797-be05-b628b59dfb7f"
}
}
Executes the quote identified by quote_id. The completed trade is submitted to settlement via the 00SCXM
platform.
Body parameters include:
quote_id
(required) the identifier of the quote to execute, which is provided in response to aGET /convert_withdraw/rfq
request
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the RFQ. | string |
quote | The quote object that was executed. | quote |
trade_id | The unique identifier assigned to the trade, which is the same trade_id as found in a GET /trades requestNote: the quote_id will be saved as the client_trade_id . |
string |
status | The status of the trade, e.g. Completed . |
string |
Payments
POST /payments
const createPayment = () => {
const timestamp = Math.round(Date.now() / 1000)
const body = {
participant_code: 'ALI123',
external_account_id: '0f68333e-2114-469d-b505-c850d776e063',
trade_id: '0f68333e-2114-469d-b505-c850d776e061',
description: 'payment'
}
const payload = timestamp + 'POST' + '/payments/external_accounts' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/payments`, options)
}
body = {
'participant_code': 'ALI123',
'external_account_id': '0f68333e-2114-469d-b505-c850d776e063',
'trade_id': '0f68333e-2114-469d-b505-c850d776e061',
'description': 'payment'
}
accounts = make_seed_request('POST', '/payments', body)
Sample response
{
"request_id": "0f68333e-2114-469d-b505-c850d776e063",
"participant_code": "ALI123",
"transaction_id": "0f68333e-2114-469d-b505-c850d776e061",
"trade_id": "0f68333e-2114-469d-b505-c850d776e061",
"description": "payment",
"amount": "7.66",
"status": "posted",
"transfer_type": "credit",
"external_account_id": "0f68333e-2114-469d-b505-c850d776e063",
"created_at": "2023-08-19T23:15:31.000Z"
}
This endpoint enables platforms to request an ACH transaction for the end customer. Zero Hash will release crypto to the end customer once their funds have settled. Platforms must work with their relationship manager to opt-in to same day or standard ACH.
Request body:
Parameter | Description | Type |
---|---|---|
participant_code | The code of the participant that wants to create a new ACH transaction. | string |
external_account_id | The unique identifier that Zero Hash generates to identify the external account. Received from POST/payments/external_accounts | string |
trade_id | The unique identifier of the trade acquired through GET /liquidity/rfq. Required if making an on-demand trade, not required if pre-funding an account. | string |
description | Descriptor that travels with the ACH transaction, e.g. “CRYPTO TRD”, optional and limited to 10 characters. (10 character limit string) | string |
Additional fields in response:
Parameter | Description | Type |
---|---|---|
request_id | The unique identifier generated by Zero Hash associated with the request. | string |
amount | The final amount of the ACH transaction. | string |
transaction_id | The unique identifier generated by Zero Hash for the transaction. | string |
status | The current status of the payment transaction. | string |
transfer_type | Indicates if the payment is a credit or a debit. | string |
created_at | Timestamp when the payment was created. | string |
POST /payments/external_accounts
const createExternalAccount = () => {
const timestamp = Math.round(Date.now() / 1000)
const body = {
participant_code: 'ALI123',
account_nickname: 'test1',
account_number: '123456789',
routing_number: '011401533',
account_type: 'checking'
}
const payload = timestamp + 'POST' + '/payments/external_accounts' + JSON.stringify(body)
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/payments/external_accounts`, options)
}
body = {
'participant_code': 'ALI123',
'account_nickname': 'test1',
'account_number': '123456789',
'routing_number': '011401533',
'account_type': 'checking'
}
accounts = make_seed_request('POST', '/payments/external_accounts', body)
Sample response
{
"request_id": "0f68333e-2114-469d-b505-c850d776e063",
"participant_code": "ALI123",
"platform_code": "TES123",
"account_nickname": "test1",
"account_type": "checking",
"external_account_id": "0f68333e-2114-469d-b505-c850d776e063",
"created_at": "1975-08-19T23:15:30.000Z"
}
Creates a new external account object that is required when generating payment transactions.
Request body:
Parameter | Description | Type |
---|---|---|
participant_code | The participant code of the Platform’s participant that the external account will be associated with. | string |
account_nickname | The account nickname of the external account, i.e. “Primary Checking” | string |
account_number | The full bank account number of the external account. | string |
routing_number | The routing number of the bank where the external account is held. | string |
account_type | Either “checking” or “savings” and indicates what type of account the external account is. | string |
Additional fields in response:
Parameter | Description | Type |
---|---|---|
external_account_id | The unique identifier that Zero Hash generates to identify the external account. | string |
GET /payments/external_accounts
const getExternalAccounts = () => {
const timestamp = Math.round(Date.now() / 1000)
const participantCodes = 'ALI123,TES123'
const payload = `${timestamp}GET/payments/external_accounts?participants=${participantCodes}&page=1&size=20{}`
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
json: true
}
return request.get(`https://api.zerohash.com/payments/external_accounts?participants=ALI123,TES123&page=1&size=20`, options)
}
accounts = make_seed_request('GET', '/payments/external_accounts', {'participants': 'ALI123,TES123', 'page': 1, 'size': 20})
Sample response
{
"message": [
{
"request_id": "0f68333e-2114-469d-b505-c850d776e063",
"account_number": "123456789",
"routing_number": "011401533",
"participant_code": "ALI123",
"platform_code": "TES123",
"account_nickname": "test1",
"account_type": "checking",
"external_account_id": "0f68333e-2114-469d-b505-c850d776e063",
"created_at": "1975-08-19T23:15:30.000Z",
"updated_at": "1975-08-19T23:15:30.000Z"
}
],
"page": 1,
"total_pages": 1,
"page_size": 20,
"count": 10
}
Used to get a list of external_accounts associated with a Platform’s participants.
Query parameters include:
participants
(optional) list of participant codes that can be used to filter for external accounts, example: ALI123,TES123.page
(optional) for paginating through the list of accounts.size
(optional) for paginating through the list of accounts.
Response:
Parameter | Description | Type |
---|---|---|
request_id | The unique identifier generated by Zero Hash associated with the request. | string |
participant_code | The participant code of the Platform’s participant that the external account will be associated with. | string |
account_nickname | The account nickname of the external account, i.e. “Primary Checking” | string |
account_number | The full bank account number of the external account. | string |
routing_number | The routing number of the bank where the external account is held. | string |
account_type | Accepts either “checking” or “savings” and indicates what type of account the external account is. | string |
external_account_id | The unique identifier that Zero Hash generates to identify the external account. | string |
GET /payments/status
const getPaymentStatus = () => {
const timestamp = Math.round(Date.now() / 1000)
const payload = `${timestamp}GET/payments/status{}`
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
json: true
}
return request.get(`https://api.zerohash.com/payments/status`, options)
}
status = make_seed_request('GET', '/payments/status', {})
Sample response
{
"message": [
{
"transaction_id": "0f68333e-2114-469d-b505-c850d776e061",
"participant_code": "ALI123",
"amount": "12.01",
"status": "posted",
"transfer_type": "credit",
"bank_transfer_id": "0f68333e-2114-469d-b505-c850d776e061",
"created_at": "1975-08-19T23:15:30.000Z",
"updated_at": "1975-08-19T23:15:30.000Z"
}
],
"page": 1,
"total_pages": 1,
"page_size": 200,
"count": 10
}
This is an endpoint that a Platform can use to get the current status of payment transactions.
Query parameters include:
start_date
(optional) as a unix timestamp.end_date
(optional) as a unix timestamp.participant
(optional) takes a participant_code that the Platform has a relationship with.transaction_id
(optional) query for a specific transaction_id.trade_id
(optional) query for payment associated with a specific trade_id.status
(optional) query for specific transaction status. Acceptable transaction statuses are -submitted
,pending
,posted
,failed
, andreversed
. Click here for more details on payment transaction statuses.page
(optional) - for paginating through the list of accounts.size
(optional) - for paginating through the list of accounts.
Response:
Parameter | Description | Type |
---|---|---|
transaction_id | The unique identifier generated by Zero Hash for the transaction. | string |
trade_id | If the payment is associated with a trade a trade_id will be present here otherwise it will be Null. | string |
participant_code | The Platform’s participant that the payment is associated with. | string |
amount | The final amount of the ACH transaction. | string |
status | The current status of the payment transaction. Click here for more details on payment transaction statuses. | string |
transfer_type | Indicates if the payment is a credit or a debit. | string |
bank_transfer_id | A unique identifier that can be used to trace the transaction. | string |
created_at | Timestamp when the payment was created. | timestamp |
updated_at | Timestamp when the payment status was last changed. | timestamp |
GET /payments/history
const getPaymentHistory = () => {
const timestamp = Math.round(Date.now() / 1000)
const participantCode = 'ALI123'
const payload = `${timestamp}GET/payments/history?participant=${participantCode}&page=1&size=20{}`
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
json: true
}
return request.get(`https://api.zerohash.com/payments/history?participant=ALI123&page=1&size=20`, options)
}
history = make_seed_request('GET', '/payments/history', {'participant': 'ALI123', 'page': 1, 'size': 20})
Sample response
{
"message": [
{
"transaction_id": "0f68333e-2114-469d-b505-c850d776e061",
"participant_code": "ALI123",
"external_account_id": "0f68333e-2114-469d-b505-c850d776e063",
"amount": "12.01",
"bank_fee": "12.01",
"ach_network": "ach",
"transfer_type": "credit",
"status_history": [
{
"status": "posted",
"timestamp": "1975-08-19T23:15:30.000Z"
}
],
"trade_id": "0f34533e-2114-469d-b505-c850d776e061",
"bank_transfer_id": "0f68333e-2114-469d-b505-c850d776e061",
"created_at": "1975-08-19T23:15:30.000Z",
"updated_at": "1975-08-19T23:15:30.000Z"
}
],
"page": 1,
"total_pages": 1,
"page_size": 20,
"count": 10
}
Platforms can use this endpoint to get extended details about payment transactions which includes the full status change history.
Query parameters include:
participant
(optional) takes a participant_code that the Platform has a relationship with.page
(optional) - for paginating through the list of accountssize
(optional) - for paginating through the list of accountstransfer_type
(optional) accepts the following values: credit or debit
Response:
Parameter | Description | Type |
---|---|---|
transaction_id | The unique identifier generated by Zero Hash for the transaction. | string |
trade_id | Is returned if the payment is associated with a trade otherwise will be Null . |
string |
participant_code | The Platform’s participant that the payment is associated with. | string |
external_account_id | The external account that is associated with the payment. | string |
amount | The final amount of the ACH transaction. | string |
bank_fee | The fee amount that the Platform is wanting to charge the participant for the payment. | string |
ach_network | The network that the payment is being transmitted. | string |
status_history | The list of status objects, showing the history of status changes.
|
array |
transfer_type | Indicates if the payment is a credit or a debit. | string |
bank_transfer_id | The unique identifier that can be used to trace the transaction. | string |
created_at | The timestamp when the payment was created. | timestamp |
updated_at | The timestamp when the payment status was last changed. | timestamp |
Payments Transaction Status
Status | Description |
---|---|
submitted | Payment transaction request has been successfully received by Zero Hash. |
pending | The payment has been created and is awaiting confirmation by the appropriate payment network that it has settled. Depending on the payment network the transaction can sit in a pending status for different periods of time. |
posted | The payment has been successfully sent to the receiving bank account. |
failed | The sending of the payment failed. This status would only occur after the transaction goes to a pending status. |
reversed | The payment was returned which can happen for different reasons such as inaccurate receiving bank details or the transaction was deemed unauthorized. This would only follow a transaction that has gone to a posted status. |
Rewards
POST /rewards
const issueReward = (customer: string, asset: string, notional: string) => {
const body = `{
underlying: ${underlying},
quoted_currency: 'USD',
total: ${notional}
participant_code: ${customer}
}`
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/rewards' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/rewards`, options)
}
body = {
'underlying': 'BTC',
'quoted_currency': 'USD',
'total': "500.00",
'participant_code': 'CUST01'
}
accounts = make_seed_request('POST', '/rewards', body)
Sample Response
{
"request_id": "14f8ebb8-7530-4aa4-bef9-9d73d56313f3",
"quote": {
"request_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3",
"participant_code": "CUST01",
"underlying_currency": "BTC",
"quoted_currency": "USD",
"side": "BUY",
"quantity": "1",
"price": "11430.90",
"quote_id": "5cd07738b861c31e3bd61467BTC1Buy1568311644602",
"expire_ts": 1568311649602,
"obo_participant":{
"participant_code":"20XRLH",
"account_group":"WRD1K0",
"account_label":"general"
},
"transaction_timestamp": 1568311649600
},
"trade_id": "ba97133e-ab15-4c86-86c1-86671b8420bc",
"status": "Completed"
}
Executes a trade to issue a reward in a certain asset. See one-pager here for more details.
Optional request header include:
Parameter | Description | Type |
---|---|---|
X-REQUEST-ID | Include a X-REQUEST-ID in the request header to ensure idempotent rewards requests | UUID |
Body parameters include:
underlying
(required) the underlying asset for to be rewarded.quoted_currency
(required) the quoted asset for purchase of the rewardquantity
(optional) the desired amount of theunderlying
for the quote (eitherquantity
ortotal
must be provided)total
(optional) the desired amount of thequoted_currency
for the quote (eitherquantity
ortotal
must be provided)participant_code
(required) the participant that is receiving the reward. This is the platform's customer.account_label
(optional) the account label associated with the account.
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the RFQ | string |
quote | The quote object that was executed | quote |
trade_id | The unique identifier assigned to the trade, which is the same trade_id as found in a GET /trades requestNote: the quote_id will be saved as the client_trade_id |
string |
status | The status of the trade, e.g. Completed |
string |
Awards
These endpoints can be used to facilitate Awards payments as part of a promotional program, prize pool, bonus pool, giveaway, etc. See release notes here for more information
POST /awards/fund
Specify the amount, quoted currency, and asset that you intend to ultimately distribute to your customers via the POST /awards/distribute endpoint.
const fundAwards = (asset: string, notional: string) => {
const body = `{
asset: ${asset},
total: ${notional}
}`
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/awards' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/awards/fund`, options)
}
body = {
'asset': 'BTC',
'total': "500.00",
}
awards = make_seed_request('POST', '/awards/fund', body)
Sample Response
{
"request_id": "14f8ebb8-7530-4aa4-bef9-9d73d56313f3",
"quote": {
"request_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3",
"participant_code": "CUST01",
"underlying_currency": "BTC",
"quoted_currency": "USD",
"side": "BUY",
"quantity": "1",
"price": "11430.90",
"quote_id": "5cd07738b861c31e3bd61467BTC1Buy1568311644602",
"expire_ts": 1568311649602,
"transaction_timestamp": 1568311649600
},
"trade_id": "ba97133e-ab15-4c86-86c1-86671b8420bc",
"status": "Completed"
}
Body parameters include:
underlying
(required) the underlying asset for to be awarded.quoted_currency
(required) the quoted asset for purchase of the rewardquantity
(optional) the desired amount of theunderlying
for the quote (eitherquantity
ortotal
must be provided)total
(optional) the desired amount of thequoted_currency
for the quote (eitherquantity
ortotal
must be provided)
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the RFQ | string |
quote | The quote object that was executed | quote |
trade_id | The unique identifier assigned to the trade, which is the same trade_id as found in a GET /trades requestNote: the quote_id will be saved as the client_trade_id |
string |
status | The status of the trade, e.g. Completed |
string |
POST /awards/distribute
Evenly distribute the purchased crypto among the specified customers.
const distributeAwards = (asset: string, quantity: string, customer_participant_codes: string[]) => {
const body = `{
asset: ${asset},
quantity: ${quantity}
participant_codes: ${customer_participant_codes}
}`
const timestamp = Math.round(Date.now() / 1000)
const payload = timestamp + 'POST' + '/awards' + body
const decodedSecret = Buffer.from(apiSecret, 'base64')
const hmac = crypto.createHmac('sha256', decodedSecret)
const signedPayload = hmac.update(payload).digest('base64')
// SET HEADERS
const headers = {
'X-SCX-API-KEY': 'public_key',
'X-SCX-SIGNED': signedPayload,
'X-SCX-TIMESTAMP': timestamp,
'X-SCX-PASSPHRASE': 'passphrase'
}
const options = {
headers,
body,
json: true
}
return request.post(`https://api.zerohash.com/awards/distribute`, options)
}
body = {
'asset': 'BTC',
'quantity': ".001",
'participant_codes': [
'CUST01',
'CUST02',
]
}
awards = make_seed_request('POST', '/awards/distribute', body)
Sample Response
{
"request_id": "14f8ebb8-7530-4aa4-bef9-9d73d56313f3",
"confirms": [
{
"participant_code": "CUST01",
"trade_id": "ce819fe8-b1d7-43bb-961c-e09ede0988d3"
},
{
"participant_code": "CUST02",
"trade_id": "ba97133e-ab15-4c86-86c1-86671b8420bc"
}
]
}
Body parameters include:
asset
(required) the asset for to be awarded.quantity
(required) the desired amount of theasset
for to be awarded to each customer in the requestparticipant_codes
(required) the list of customers to receivequantity
amount of reward
Response:
Parameter | Description | Type |
---|---|---|
request_id | The identifier of the request | string |
confirms | A list of participant_code plus trade identifiers for the executed trades confirm | confirm |
Market Data
GET /market_data/ohlcv
Sample Response
{
"message": [
{
"time": 1683065100,
"high": 28730.35,
"low": 28710.94,
"open": 28711.99,
"underlying_volume": 7.682,
"quoted_volume": 220637.37,
"close": 28724.54,
"average_transaction_price": 28721.34
}
]
}
Query for the historical data of open, high, low, close, underlying_volume and quoted_volume.
The following query parameters are required:
underlying
quoted_currency
time_frame
Parameter | Description | Type |
---|---|---|
underlying | First symbol in a pair | string |
quoted_currency | Second symbol in a pair. Usually a fiat currency - USD , BRL , AUD , GBP or EUR |
string |
time_frame | Specifies the OHLCV intervals - minute , hourly or daily |
string |
limit | Limit to how much data will be returned, max 2000 | number |
data_end_date | Pulls all available data until this date. Limit 2000 datapoints at a time. Use this to pull all available historical data by moving this date back. | timestamp |
all_data | Applies only to the daily time frame. Pulls all available historical data |
boolean |
GET /market_data/news/latest
Sample Response
[
{
"publishedOn":{
"seconds":1684928,
"nanos":819000000
},
"imageUrl":"/resources/news/21/example.jpeg",
"title":"Example Title",
"url":"https://www.externalsource.com/all/article_url/",
"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
"tagsList":[
"All"
],
"language":"EN",
"upVotes":2,
"downVotes":5,
"categoriesList":[
"MARKET|BTC"
],
"sourceInfo":{
"name":"ExampleSource",
"img":"/images/news/default/example.png",
"language":"EN"
},
"source":"exampleSource"
}
]
Query for the latest Market News Articles.
Query Parameters
Parameter | Description | Type |
---|---|---|
news_source | Publisher of the article. Available sources can be found in GET /marketdata/news/feeds | array |
categories | Filter by category. Available categories can be found at GET /marketdata/news/categories | array |
exclude_categories | Categories to exclude. | array |
lookback | Pulls news articles before this timestamp. | string |
language | Filter by using ‘EN’ for English or ‘PT’ for Portuguese. | string |
sort_by | ‘latest’ or ‘popular’ | string |
Latest News Articles Response:
Parameter | Description | Type |
---|---|---|
published_on | Timestamp when the article was published | timestamp |
image_url | Can be sent to the GET /market_data/image endpoint to get the image content. |
string |
title | Article title | string |
url | Link to news article | string |
body | Text of the article | string |
tags | Associated tags | array |
language | English (EN) or Portuguese (PT) | string |
up_votes | Number of upvotes for article | number |
down_votes | Number of downvotes for article | number |
categories | Associated categories with the article. Availalbe categories can be accessed via GET /marketdata/news/categories | array |
GET /market_data/news/feeds
Sample Response
[
{
"key":"examplekey",
"newsSource":"ExampleSource",
"img":"/images/news/default/example.png",
"language":"EN"
}
]
Query for the available Market News Feeds.
This endpoint receives no parameters.
Market News Feeds Response
Parameter | Description | Type |
---|---|---|
key | Name of news feed | string |
news_source | Source of news feed | string |
img | Can be added at the end of the GET /market_data/image endpoint to get the image content |
string |
language | Language of the article, English (EN) or Portuguese (PT) | string |
GET /market_data/news/categories
Sample Response
[
{
"categoryName":"DOGE",
"wordsAssociatedWithCategoryList":[
"DOGE",
"DOGECOIN"
]
}
]
Query for the available Market News Categories.
Returns a list of available categories, to be used in GET /news/latest query.
This endpoint receives no parameters.
Market News Categories Response
Parameter | Description | Type |
---|---|---|
category_name | Name of category | string |
words_associated_with_category | Additional words associated with each category | string |
GET /market_data/symbol_data
Sample Response
[
[
"BTC",
{
"marketDataMap": [
[
"EUR",
{
"underlyingSymbol": "BTC",
"quotedSymbol": "EUR",
"price": {
"value": "24774.07"
},
"lastTimestamp": {
"seconds": 1684931,
"nanos": 317000000
},
"median": {
"value": "24763.233"
},
"lastVolume": {
"value": "0.00665944"
},
"lastUnderlyingVolume": {
"value": "164.86775608"
},
"lastTradeId": "286032218",
"dayUnderlyingVolume": {
"value": "1730.2752600699723"
},
"dayQuotedVolume": {
"value": "43002041.91778815"
},
"h24UnderlyingVolume": {
"value": "3095.34965215"
},
"h24QuotedVolume": {
"value": "77536066.6513729"
},
"dayOpen": {
"value": "25273.27"
},
"dayHigh": {
"value": "25275.13"
},
"dayLow": {
"value": "24720.58"
},
"h24Open": {
"value": "25353.18"
},
"h24High": {
"value": "25395.88"
},
"h24Low": {
"value": "24706.05"
},
"hourUnderlyingVolume": {
"value": "94.92060853000024"
},
"hourQuotedVolume": {
"value": "2351647.5504815634"
},
"hourOpen": {
"value": "24821.51"
},
"hourHigh": {
"value": "24822.2"
},
"hourLow": {
"value": "24752.67"
},
"h24Change": {
"value": "-579.1100000000006"
},
"h24PctChange": {
"value": "-2.2841710586206565"
},
"dayChange": {
"value": "-499.2000000000007"
},
"dayPctChange": {
"value": "-1.9752093812949443"
},
"hourChange": {
"value": "-47.43999999999869"
},
"hourPctChange": {
"value": "-0.19112455285757673"
},
"supply": 19382375,
"mktcap": {
"value": "480180315016.25"
},
"circulatingSupply": 19382375,
"circulatingSupplyMktcap": {
"value": "480180315016.25"
},
"h24UnderlyingTotalVolume": {
"value": "81816.23700409418"
},
"h24QuotedTotalVolume": {
"value": "2027772840.3705523"
},
"imageUrl": "//media/37746251/btc.png"
}
],
[
"USD",
{
"underlyingSymbol": "BTC",
"quotedSymbol": "USD",
"price": {
"value": "26725.97"
},
(...)
}
]
]
}
]
]
Query for the available Full Symbol Data. Can query for one or multiple underlying/quoted assets.
Response contains symbol data for all underlying/quoted pairs.
Full Symbol Data Request
Parameter | Description | Required | Type |
---|---|---|---|
underlying | First symbol in a pair. | yes | array |
quoted_currency | Second symbol in a pair, often a fiat currency. | yes | array |
Full Symbol Data Response
Parameter | Description | Type |
---|---|---|
underlying | first symbol in a pair | string |
quoted_currency | second symbol in a pair, often a fiat currency | string |
price | current price of the underlying / quoted pair | float |
last_timestamp | most recent timestamp associated with the price | timestamp |
median | average price | float |
last_underlying_volume | most recent volume stated in the underlying | float |
last_quoted_volume | most recent volume stated in the quoted_currency | float |
last_trade_id | most recent trade ID | string |
day_underlying_volume | day volume stated in the underlying | float |
day_quoted_volume | day volume stated in the quoted_currency | float |
h24_underlying_volume | hour volume stated in the underlying | float |
h24_quoted_volume | hour volume stated in the quoted_currency | float |
day_open | open price for the day | float |
day_high | high price for the day | float |
day_low | low price for the day | float |
h24_open | 24 hour opening price | float |
h24_high | 24 hour high price | float |
h24_low | 24 hour low price | float |
hour_underlying_volume | hour volume stated in the underlying | float |
hour_quoted_volume | hour volume stated in the quoted_currency | float |
hour_open | hour opening price | float |
hour_high | hour high price | float |
hour_low | hour low price | float |
h24_change | 24 hour price change | float |
h24_pct_change | 24 hour percent change | float |
day_change | daily price change | float |
day_pct_change | daily percent change | float |
hour_change | hour price change | float |
hour_pct_change | hour percent change | float |
supply | total supply for the underlying | float |
mktcap | total market capitalization | float |
circulating_supply | the current supply of coins available to the public | float |
circulating_supply_mktcap | the current supply of coins available to the public, stated in the quoted_currency | float |
h24_underlying_total_volume | 24 hour total volume stated in the underlying | float |
h24_quoted_total_volume | 24 hour total volume stated in the quoted_currency | float |
image_url | Underlying asset image. Can be sent to the GET /market_data/image endpoint to get the image content |
string |
GET /market_data/image/*
Sample Requests
GET /market_data/image/resources/news/64/12223.jpeg
GET /market_data/image/images/news/122232.jpeg
GET /market_data/image//news/122232.jpeg
- This is a valid path.
//
paths are usually returned in the response ofGET /market_data/symbol_data
Receives an image path, returns image content at the path in bytes.
Image paths are returned by Market Data endpoints, in the following format:
"/source/subpath1/subpath2/.../image.jpeg"
Example of real path: "/resources/news/64/12223.jpeg"
Paths can be added at the end of this endpoint to fetch the image.
GET /market_data/image
+ /resources/news/64/12223.jpeg
This endpoint receives no query parameters.
Central Limit Order Book
POST /orders/v1/search_orders
This endpoint returns a list of your orders on the Central Limit Order Book that match the requested query parameters.
Parameter | Description | Type |
---|---|---|
account | Firm / Acount ID | string |
symbol | Trading Instrument | string |
start_time | Filter Start Time | string |
end_time | Filter End Time | string |
page_size | Orders Per page | Int |
{
"account": "firms/{FIRM-ID}/accounts/{ACCOUNT-ID}",
"symbol": "BTC/USD",
"start_time": "2023-06-21T19:15:59.620Z",
"end_time": "2023-06-21T19:15:59.620Z",
"page_size": 10,
}
body = {
"account": "firms/{FIRM-ID}/accounts/{ACCOUNT-ID}",
"symbol": "BTC/USD",
"start_time": "2023-06-21T19:15:59.620Z",
"end_time": "2023-06-21T19:15:59.620Z",
"page_size": 10,
}
send_signed_http_request('POST', '/orders/v1/search_orders', body)
Sample Response
{
"order":[
{
"id":"1670693742334484486",
"type":"ORDER_TYPE_MARKET_TO_LIMIT",
"side":"SIDE_SELL",
"order_qty":"1000",
"symbol":"BTC/USD",
"clord_id":"3135638227567779936000",
"time_in_force":"TIME_IN_FORCE_GOOD_TILL_CANCEL",
"account":"firms/{FIRM-ID}/accounts/{ACCOUNT-ID}",
"cum_qty":"0",
"avg_px":"0",
"leaves_qty":"0",
"state":"ORDER_STATE_REJECTED",
"participant":"firms/{FIRM-ID}/accounts/{ACCOUNT-ID}",
"price":"0",
"insert_time":null,
"stop_price":"0",
"min_qty":"0",
"create_time":"2023-06-19T07:33:05.727361505Z",
"all_or_none":false,
"cross_id":"",
"host_cross_id":"",
"submitting_participant":"",
"client_account_id":"",
"client_participant_id":"",
"parent_order_id":"",
"commissions_basis_points":"18",
"participate_dont_initiate":false,
"cash_order_qty":"0",
"symbol_sub_type":"",
"strict_limit":false,
"risk_check_time":null,
"collateral_memo":"",
"priority_weight":"0",
"good_till_time":null,
"context":{
"any_context":null,
"fix_context":{
"begin_string":"FIXT.1.1",
"target_comp_id":"#*{FIRM-ID}*#",
"sender_comp_id":"ZERO",
"orig_clord_id":"",
"security_type":"",
"target_sub_id":"",
"target_location_id":"",
"sender_sub_id":"{ACCOUNT-ID}",
"sender_location_id":"",
"on_behalf_of_comp_id":"",
"on_behalf_of_sub_id":""
}
},
"best_limit":false,
"immediately_executable_limit":false,
"block_trade_indicator":false,
"last_trade_id":"",
"trigger_method":"CONDITION_TRIGGER_METHOD_UNDEFINED",
"price_to_quantity_filled":{
},
"commission_notional_total_collected":"0",
"self_match_prevention_instruction":"SELF_MATCH_PREVENTION_INSTRUCTION_UNDEFINED",
"order_capacity":"ORDER_CAPACITY_UNDEFINED",
"ignore_price_validity_checks":false
},
],
"next_page_token":"2023-06-14T06:33:06.113Z_64895f222aff3a1f4c5af08f"
}
POST /orders/v1/insert_order
To place an order on the Zero Hash CLOB, you must pass the following parameters to the insert_order
endpoint.
Parameter | Description | Type |
---|---|---|
account | Firm/Account ID | string |
type | Order type (Limit) | string |
time_in_force | Time in Force | string |
side | Side of the order book | string |
order_qty | Quantity of the order | string |
price | Price of the order | string |
symbol | The Trading Instrument | string |
good_till_time | Expiry time | string |
{
"account":"firms/{FIRM-ID}/accounts/{ACCOUNT-ID}",
"type":"ORDER_TYPE_LIMIT",
"time_in_force":"TIME_IN_FORCE_GOOD_TILL_TIME",
"side":"SIDE_SELL",
"order_qty":"10000",
"price":"23000",
"symbol":"BTC/USD",
"good_till_time":"2023-06-21T20:31:03Z"
}
body = {
"account":"firms/{FIRM-ID}/accounts/{ACCOUNT-ID}",
"type":"ORDER_TYPE_LIMIT",
"time_in_force":"TIME_IN_FORCE_GOOD_TILL_TIME",
"side":"SIDE_SELL",
"order_qty":"10000",
"price":"23000",
"symbol":"BTC/USD",
"good_till_time":"2023-06-21T20:31:03Z"
}
send_signed_http_request('POST', '/orders/v1/insert_order', body)
Sample Response
{
"order_id":"1670745028203638840",
}
POST /orders/v1/cancel_order
To cancel an order on the Zero Hash CLOB, you must pass the following parameters to the cancel_order
endpoint.
Parameter | Description | Type |
---|---|---|
order_id | ID of the order to be canceled | string |
{
"order_id":"1670745028203638840"
}
body = {
"order_id":"1670745028203638840"
}
send_signed_http_request('POST', '/orders/v1/cancel_order', body)
Sample Response
{}
POST /orders/v1/list_instruments
This endpoint returns a list of the trading instruments available in the CLOB and their trading parameters.
{}
send_signed_http_request('POST', '/orders/v1/list_instruments', {})
Sample Response
{
"instruments":[
{
"symbol":"BTC/USD",
"tick_size":0.01,
"base_currency":"USD",
"multiplier":1,
"minimum_trade_qty":"1",
"start_date":{
"year":1970,
"month":1,
"day":1
},
"expiration_date":null,
"termination_date":null,
"trading_schedule":[
],
"description":"Bitcoin USD Spot",
"clearing_house":"firms/YDB0D6",
"minimum_unaffiliated_firms":"0",
"forex_attributes":{
"base_currency":"BTC",
"quote_currency":"USD"
},
"non_tradable":false,
"product_id":"BTC",
"price_limit":{
"low":"0",
"high":"0",
"low_set":false,
"high_set":false,
"relative_low":"NaN",
"relative_high":"NaN",
"relative_low_set":false,
"relative_high_set":false
},
"order_size_limit":{
"low":"0",
"high":"0",
"low_set":false,
"high_set":false,
"total_notional_low":"10000000000",
"total_notional_high":"5000000000000000",
"total_notional_low_set":true,
"total_notional_high_set":true
},
"cross_order_resting_duration":null,
"expiration_time":null,
"trade_settlement_period":"1",
"holiday_calendars":[
],
"fractional_qty_scale":"100000000",
"metadata":{
},
"state":"INSTRUMENT_STATE_OPEN",
"position_limit":"0",
"last_trade_date":null,
"last_trade_time":null,
"price_scale":"100"
},
{
"symbol":"ETH/USD",
"tick_size":0.01,
"base_currency":"USD",
"multiplier":1,
"minimum_trade_qty":"1",
"start_date":{
"year":1970,
"month":1,
"day":1
},
"expiration_date":null,
"termination_date":null,
"trading_schedule":[
],
"description":"Ethereum USD Spot",
"clearing_house":"firms/YDB0D6",
"minimum_unaffiliated_firms":"0",
"forex_attributes":{
"base_currency":"ETH",
"quote_currency":"USD"
},
"non_tradable":false,
"product_id":"ETH",
"price_limit":{
"low":"0",
"high":"0",
"low_set":false,
"high_set":false,
"relative_low":"NaN",
"relative_high":"NaN",
"relative_low_set":false,
"relative_high_set":false
},
"order_size_limit":{
"low":"0",
"high":"0",
"low_set":false,
"high_set":false,
"total_notional_low":"100000000",
"total_notional_high":"0",
"total_notional_low_set":true,
"total_notional_high_set":false
},
"cross_order_resting_duration":null,
"expiration_time":null,
"trade_settlement_period":"1",
"holiday_calendars":[
],
"fractional_qty_scale":"100000000",
"metadata":{
},
"state":"INSTRUMENT_STATE_OPEN",
"position_limit":"0",
"last_trade_date":null,
"last_trade_time":null,
"price_scale":"100"
},
],
"next_page_token":"643538bb35cbd2a93099ae14",
"eof":true
}
POST /orders/v1/get_trade_stats
This endpoint returns a list of trading stats for a given symbol.
Parameter | Description | Type |
---|---|---|
bars | Int | |
end_time | Filter End Time | string |
start_time | Filter Start Time | string |
symbol | Trading Instrument | string |
{
"bars":0,
"end_time":"2023-06-21T21:19:26Z",
"start_time":"2023-06-12T20:08:12.407Z",
"symbol":"BTC/USD"
}
body = {
"bars":0,
"end_time":"2023-06-21T21:19:26Z",
"start_time":"2023-06-12T20:08:12.407Z",
"symbol":"BTC/USD"
}
send_signed_http_request('POST', '/orders/v1/get_trade_stats', {})
Sample Response
{
"stats":{
"first":"2581860",
"last":"2889568",
"high":"2889568",
"low":"2549819",
"total_trade_count":"67",
"cleared_trade_count":"55",
"volume":"712094818",
"cleared_volume":"462910677",
"notional":"1843085487491258",
"cleared_notional":"1195355767917713"
},
"bars":[
{
"first":"2581860",
"last":"2889568",
"high":"2889568",
"low":"2549819",
"total_trade_count":"67",
"cleared_trade_count":"55",
"volume":"712094818",
"cleared_volume":"462910677",
"notional":"1843085487491258",
"cleared_notional":"1195355767917713"
}
],
"bar_start_time":[
"2023-06-12T20:08:12.407Z"
],
"bar_end_time":[
"2023-06-21T21:15:36Z"
]
}
Private Socket Feed
Overview
The private WebSocket feed provides real-time balance and price updates for streamlined processing.
Important considerations
A long-lived TCP connection such as the one used by the WebSocket can be subject to multiple issues, including but not limited to: network instabilities on client/server, timeouts, ISP, etc.. These issues are expected to happen at any point in time, thus it's fundamental to have a reconnection/resubscription mechanism in place, which you'll find samples for in the examples below.
Endpoints
- Production: wss://ws.zerohash.com
- Certification: wss://ws.cert.zerohash.com
Authentication
The same authentication mechanism used for the Web API applies to the WebSocket: all sent messages must be properly signed to ensure authenticity of the request.
import hashlib
import hmac
from base64 import b64decode, b64encode
def sign(api_key: str, method: str, route: str, json_body: str, timestamp: str) -> bytes:
"""
Given a key and data, create and sign a payload.
:param api_key: Key to sign the message with
:param method: HTTP method
:param route: Relative route.
:param json_body: JSON as a string. Usually created via json.dumps(dict)
:param timestamp: Unix Epoch time as a string
:return: Base64 encoded digest
"""
msg = bytes(timestamp + method + route + json_body, encoding='utf-8')
hm = hmac.new(key=b64decode(api_key), msg=msg, digestmod=hashlib.sha256)
return b64encode(hm.digest())
const crypto = require('crypto');
const sign = (body, secret) => {
let ts = String(Math.round(Date.now() / 1000));
let payload = ts + 'POST' + '/' + JSON.stringify(body);
let decodedSecret = Buffer.from(secret, 'base64');
let hmac = crypto.createHmac('sha256', decodedSecret);
let signedPayload = hmac.update(payload).digest('base64');
};
Basic setup
The JS and Python examples provide basic functionality for handling outgoing and incoming messages as well as a basic reconnection/resubscription mechanism in case of unexpected network failures. These examples provide a baseline to build upon, be sure to modify them in order to accomodate it to your language, library, framework and system needs.
const WebSocket = require('ws');
const crypto = require('crypto');
// NB: THESE CREDENTIALS SHOULD NOT BE STORED IN PLAINTEXT
// Keys here are kept in plaintext for the purposes of demonstration
// We encourage you to encrypt your keys and decrypt them only when being used
const KEY = '...';
const SECRET = '...';
const PASSPHRASE = '...';
const sign = (body, secret) => {
let ts = String(Math.round(Date.now() / 1000));
let payload = ts + 'POST' + '/' + JSON.stringify(body);
let decodedSecret = Buffer.from(secret, 'base64');
let hmac = crypto.createHmac('sha256', decodedSecret);
let signedPayload = hmac.update(payload).digest('base64');
};
const sendWebsocketMessage = (client, type, body, secret, key, phrase) => {
const ts = String(Math.round(Date.now() / 1000));
const payload = ts + 'POST' + '/' + JSON.stringify(body);
const decodedSecret = Buffer.from(secret, 'base64');
const hmac = crypto.createHmac('sha256', decodedSecret);
const signedPayload = hmac.update(payload).digest('base64');
let data = JSON.stringify({
messageType: type,
body: body,
key: key,
passphrase: phrase,
timestamp: ts,
signature: signedPayload
});
console.log('sending message:', data);
client.send(data);
};
const ws = new WebSocket(`wss://ws.cert.zerohash.com`);
ws.on('open', () => {
sendWebsocketMessage(ws, 'subscribe', { filter: {} }, SECRET, KEY, PASSPHRASE);
});
ws.on('message', (data) => {
console.log('received message:', JSON.parse(data));
});
ws.on('error', (data) => {
console.log('unexpected error:', data);
});
setInterval(() => {
sendWebsocketMessage(ws, 'ping', {}, SECRET, KEY, PASSPHRASE);
}, 10000);
# Even after removing type annotations, the below code works with Python 3.4+ only.
# For ease of use, Python 3.6+ is recommended if using websockets.
import asyncio
import hashlib
import hmac
import json
from asyncio.exceptions import IncompleteReadError
from base64 import b64decode, b64encode
from datetime import datetime
from logging import getLogger
from websockets.client import connect
from websockets.exceptions import ConnectionClosed, ConnectionClosedError
logger = getLogger(__name__)
# NB: THESE CREDENTIALS SHOULD NOT BE STORED IN PLAINTEXT
# Keys here are kept in plaintext for the purposes of demonstration
# We encourage you to encrypt your keys and decrypt them only when being used
WS_URL = "wss://ws.cert.zerohash.com"
API_PUBLIC_KEY = "..."
API_PRIVATE_KEY = "..."
API_PASSPHRASE = "..."
class Feed:
async def connect_private(self):
"""Connect to the private websocket endpoint that requires authentication."""
async for conn in connect(WS_URL):
t = str(int(datetime.now().timestamp()))
sig = self._sign(API_PRIVATE_KEY, "POST", "/", json.dumps({"filter": {}}, separators=(",", ":")), t)
msg = json.dumps(
{
"messageType": "subscribe",
"body": {"filter": {}},
"key": API_PUBLIC_KEY,
"passphrase": API_PASSPHRASE,
"timestamp": t,
"signature": sig.decode("utf-8"),
},
indent=2,
)
try:
print("sending message:", msg)
await conn.send(msg)
while True:
self._message_handler(await conn.recv())
# Be sure to handle other relevant network issues/exception provided by your WebSocket library of choice
except ConnectionClosed or ConnectionClosedError or IncompleteReadError as e:
print("Network issue encountered, backing off and reconnecting. Details: ", e)
asyncio.sleep(5)
continue
def _message_handler(self, msg: str):
"""Simple message handling for data received from the WebSocket."""
try:
msg = json.loads(msg)
except json.JSONDecodeError:
logger.error("Error loading JSON message from server: {}".format(msg))
return
if "message" in msg:
logger.info(msg["message"])
return
print("received message:", msg)
def _sign(self, api_key: str, method: str, route: str, json_body: str, timestamp: str) -> bytes:
msg = bytes(timestamp + method + route + json_body, encoding="utf-8")
hm = hmac.new(key=b64decode(api_key), msg=msg, digestmod=hashlib.sha256)
return b64encode(hm.digest())
loop = asyncio.get_event_loop()
loop.run_until_complete(Feed().connect_private())
Balances
The balance feed provides real-time updates when the balance is updated for any accounts that match the subscription filters.
Initial Subscription
In order to subscribe to the balance feed, a message of type subscribe
must be sent.
Parameter | Description | Type |
---|---|---|
body{} | An object used to restrict what is returned in the subscription. This must be included but can be empty. | object |
messageType | Subscription message type - subscribe |
string |
topic | Topic to subscribe to - balances for the balance feed. Can be omitted. |
string |
useMultiChainAssetFormat | Include chain in asset names, e.g. AAVE.ETH vs. AAVE for the balance feed. Can be omitted. Default is false |
boolean |
key | Your public key | string |
passphrase | Your passphrase | string |
timestamp | Time in seconds since Unix Epoch | string |
signature | your hmac signature | string |
Subscription Filters
Optional filters you can include within the body
to restrict which balance updates will be sent by the WebSocket:
Parameter | Description | Type |
---|---|---|
filter{} | A filter object used to specify account characteristics | object |
The filter{}
object can include:
Parameter | Description | Type |
---|---|---|
account_owner | The participant code for the specific participant you want updates for | string |
account_group | The group that you want updates for | string |
account_type | The type that you want updates for - available , collateral , payable , receivable or collateral_deficiency |
string |
asset | The asset code you would like updates for | string |
Subscription Response
Subscription Response
{
"messageType": "initial-balance",
"body": [
{
"account_id": "12345",
"participant_code": "ABC123",
"account_group": "XYZ456",
"account_label": "general",
"account_type": "available",
"asset": "BTC",
"balance": "1.00",
"run_id": 1,
"run_type": "unknown"
}
]
}
Upon successfully subscribing you will receive an initial-balance
message which includes a snapshot of all current account balances that meet your subscription criteria.
Parameter | Description | Type |
---|---|---|
account_id | Unique ID of the specific account | string |
participant_code | The code of the participant that owns the account | string |
account_group | The group that the account is a part of | string |
account_label | The account label to filter the response by | string |
account_type | available , collateral , payable , receivable or collateral_deficiency |
string |
asset | The asset code for the specific account, e.g. USD |
string |
balance | The balance in the account | string |
run_id | A unique ID for the particular run | int |
run_type | The type of run | string |
Balance Update
Sample Response
{
"messageType": "balance-updated",
"body": {
"participant_code": "ABC123",
"account_group": "XYZ456",
"account_label": "general",
"account_type": "available",
"asset": "BTC",
"balance": "1.01",
"run_id": 1,
"run_type": "settlement",
"movements": [
{
"movement_timestamp": "2021-11-04T02:50:16.202915702Z",
"movement_id": "EFG456",
"movement_type": "final_settlement",
"deposit_reference_id": "deposit 123",
"change": "123.123",
"source": "deposit 123 sending address",
"received_address": "deposit 123 received address"
}
],
"run_timestamp": "2021-11-04T02:51:16.202911633Z"
}
}
After receiving the initial-balance
message, you will be sent incremental balance-updated
messages, which show any balance changes to accounts that meet your subscription criteria.
Parameter | Description | Type |
---|---|---|
participant_code | The code of the participant that owns the account | string |
account_group | The group that the account is a part of | string |
account_label | The account label to filter the response by | string |
account_type | available , collateral , payable , receivable or collateral_deficiency |
string |
asset | The asset code for the specific account, e.g. USD |
string |
balance | Updated balance value | string |
run_id | A unique ID for the particular run | string |
run_type | The type of run | string |
run_timestamp | Timestamp when the account balance was updated | timestamp |
movements[] | An array of movements related to the specific account update Refer to the GET /accounts/:account_id/movements section for field definitions |
array |
Prices
The price feed provides real-time Bid/Ask price levels of up to a depth of 10 for the available symbols.
Listing available symbols
The symbols available for subscription can be fetched by sending a message of type info
and with the topic set to available-symbols
.
{
"messageType": "info",
"topic": "available-symbols",
"key": "API_PUBLIC_KEY",
"passphrase": "PASSPHRASE",
"timestamp": "TIMESTAMP",
"signature": "SIGNATURE"
}
Available symbols response
{
"messageType": "info",
"topic": "available-symbols",
"body": {
"message": [
"BTC/USD",
"ETH/USD",
"LTC/USD",
...
]
}
}
Subscribing to a Symbol
In order to subscribe to the price feed, a message of type subscribe
must be sent.
{
"messageType": "subscribe",
"topic": "prices",
"body": {
"filter": {
"symbol": "BTC/USD"
}
},
"key": "API_PUBLIC_KEY",
"passphrase": "PASSPHRASE",
"timestamp": "TIMESTAMP",
"signature": "SIGNATURE"
}
Parameter | Description | Type |
---|---|---|
body{} | An object used to filter which symbol will be subscribed to. This is a required field for the price feed. | object |
messageType | Subscription message type - subscribe |
string |
topic | Topic to subscribe to - prices for the price feed |
string |
key | Your public key | string |
passphrase | Your passphrase | string |
timestamp | Time in seconds since Unix Epoch | string |
signature | your hmac signature | string |
Subscription response
{
"body": "successfully subscribed to the BTC/USD feed",
"messageType": "subscribe"
}
Price update
After successfully subscribing to a symbol, you will be sent price-updated
messages whenever the price is updated.
Parameter | Description | Type |
---|---|---|
bid_levels[] | Array of Bid price levels (up to a depth of 10) | string |
ask_levels[] | Array of Ask price levels (up to a depth of 10) | string |
symbol | The symbol which was subscribed to | string |
messageType | Price update message type - price-update |
string |
The price level object comprises these fields:
Parameter | Description | Type |
---|---|---|
price | The level price | string |
quantity | The level quantity | string |
side | The level side - buy or sell |
string |
{
"messageType": "price-update",
"body": {
"symbol": "BTC/USD",
"bid_levels": [
{
"price": "42260.4677",
"quantity": "0.59",
"side": "buy"
},
{
"price": "42255.445175",
"quantity": "1.77",
"side": "buy"
},
{
"price": "42251.475275",
"quantity": "3.54",
"side": "buy"
},
{
"price": "42245.941475",
"quantity": "7.09",
"side": "buy"
}
],
"ask_levels": [
{
"price": "42317.16195",
"quantity": "0.59",
"side": "sell"
},
{
"price": "42320.83275",
"quantity": "1.77",
"side": "sell"
},
{
"price": "42324.872625",
"quantity": "3.54",
"side": "sell"
},
{
"price": "42330.139425",
"quantity": "7.09",
"side": "sell"
}
]
}
}
Maintaining Subscription
Once subscribed to any of the above feeds, a ping
message must be sent every 20 seconds to keep the subscription active; otherwise, the connection will be closed.
Ping Message
{
"messageType": "ping",
"key": "API_PUBLIC_KEY",
"passphrase": "PASSPHRASE",
"timestamp": "TIMESTAMP",
"signature": "SIGNATURE"
}