Exchange-official-API-docs

Official Documentation for the Exchange APIs and Streams


Change Log


Introduction

Welcome to the Exchange API documentation for developers. Here you can find a breakdown of the API endpoints and how to use them.


General Information

Endpoint

The root URL for API access: https://api.crypto.com

The root URL for WebSocket access wss://ws.crypto.com/kline-api/ws

All requests must be made via HTTPS protocol. For POST and DELETE requests, the Content-Type in the request must be application/x-www-form-urlencoded.

Generate the API Key

Before sending any requests, you'll need to generate a new API key. This can be done via the web interface in【User Center】-【API】. After generating the key, there are two things you need to record:

API Key and Secret are randomly generated by the system and can not be modified.

You can optionally specify a whitelist of IP addresses when generating the API Key. If specified, the API can only be used from the whitelisted IP addresses.

Request Signing

Some endpoints are only accessible by authenticated users. The authentication is based on a pair of API Key and SHA-256 of the HTTP request parameter along with the API Secret Key (and should never explicitly include the API Secret Key in your request).

The algorithm for generating the SHA-256 signature is as follows:

  1. Sort the HTTP request parameter names in ascending order.

  2. For each parameter name, if the corresponding parameter value is not null/empty, append namevalue (without any other separators) to the buffer.

  3. Use SHA-256 to hash the buffer string.

Example:

api_key = mZhlB7z8dDXXdL74uwoIoqAtPQSpY6Mk
  time = 1573789761928
  secret_key = qg7fPyVj43tvfWBX83pSB7s8ZajHD1ve

  sign=sha256("api_key" + "mZhlB7z8dDXXdL74uwoIoqAtPQSpY6Mk" + "time" + "1573789761928" + "qg7fPyVj43tvfWBX83pSB7s8ZajHD1ve")
      

Response Status Code

HTTP Error Code

Unless otherwise specified, all responses are a JSON object with the following fields. The user can observe the code and msg fields for more detailed error information.

{
      code: 0, // zero means ok, non-zero means err
      msg: "suc", // "suc" means successful, if code is non-zero then this contains the error message
      data: ... // the response data, if any
  }
      

Market Symbols

Many APIs requires a symbol field which is the name of a market (or the name of the Trading Pair). The following table has a few examples of symbols:

Currency Name xxx-cro xxx-btc xxx-usdt
cro - crobtc crousdt
btc btccro - btcusdt
eth ethcro ethbtc ethusdt
xrp xrpcro xrpbtc xrpusdt

API Reference

There are three groups of API endpoints:

API Group Request Signing Description
Market APIs Not needed Market public data such as ticker, order book, etc…
User APIs Required User account activities such as checking account balance, create order, cancel order, etc…
WebSocket API Not needed Market public data such as ticker, order book, etc…

Users are recommended to use WebSocket API instead of Market API because the former is faster and more efficient.

An overview of all the available API endpoints are listed as follows:

Group Path Method Allowed Parameters Action
Market /v1/symbols GET (null) List all available market symbols
Market /v1/ticker GET (null) Get tickers in all available markets
Market /v1/ticker GET symbol Get ticker for a particular market
Market /v1/klines GET period, symbol Get k-line data over a specified period
Market /v1/trades GET symbol Get last 200 trades in a specified market
Market /v1/ticker/price GET (null) Get latest execution price for all markets
Market /v1/depth GET symbol, type Get the order book for a particular market
User /v1/account POST api_key, time, sign List all account balance of user
User /v1/order POST api_key, fee_is_user_exchange_coin, price, side, symbol, time, type, volume, sign Create an order
User /v1/showOrder POST order_id, symbol, time, sign Get order detail
User /v1/orders/cancel POST api_key, order_id, symbol, time, sign Cancel an order
User /v1/cancelAllOrders POST api_key, symbol, time, sign Cancel all orders in a particular market
User /v1/openOrders POST api_key, page, pageSize, symbol, time, sign List all open orders in a particular market
User /v1/allOrders POST api_key, endDate, page, pageSize, startDate, symbol, time, sign List all orders in a particular market
User /v1/myTrades POST api_key, endDate, page, pageSize, startDate, symbol, time, sign List all executed orders

Note: For User API calls, there are three more parameters in each requests -- api_key, time and sign.

Group Request or Subscribe Channel Description
WS req review Request current tickers in all available markets
WS sub market_${symbol}_ticker Subscribe new tickers for a particular market
WS req market_${symbol}_kline_1min
market_${symbol}_kline_5min
market_${symbol}_kline_15min
market_${symbol}_kline_30min
market_${symbol}_kline_60min
market_${symbol}_kline_1day
market_${symbol}_kline_1week
market_${symbol}_kline_1month
Request history k-line data over a specified period
WS sub market_${symbol}_kline_1min
market_${symbol}_kline_5min
market_${symbol}_kline_15min
market_${symbol}_kline_30min
market_${symbol}_kline_60min
market_${symbol}_kline_1day
market_${symbol}_kline_1week
market_${symbol}_kline_1month
Subscribe new k-line data over a specified period
WS req market_${symbol}_trade_ticker Request last 200 trades in a specified market
WS sub market_${symbol}_trade_ticker Subscribe: new trades in a specified market
WS sub market_${symbol}_depth_step[0-2] Subscribe: - order book for a particular market (Full update)

Market API

List all available market symbols

  1. Endpoint URL: /v1/symbols
  2. Method: GET
  3. Description: queries all transaction pairs and precision supported by the system.
  4. This is a public interface, request signature is not needed
  5. Request Parameter: no parameter is allowed
  6. Response Content-Type: application/json
  7. Response JSON fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "code": "0",
      "msg": "suc",
      "data": [
          {
              "symbol": "ethbtc", // Transaction pairs
              "count_coin": "btc", // Money of Account
              "amount_precision": 3, // Quantitative precision digits (0 is a single digit)
              "base_coin": "eth", // Base currency
              "price_precision": 8 // Price Precision Number (0 is a single digit) 
          },
          {
              "symbol": "ltcbtc",
              "count_coin": "btc",
              "amount_precision": 2,
              "base_coin": "ltc",
              "price_precision": 8
          },
          {
              "symbol": "etcbtc",
              "count_coin": "btc",
              "amount_precision": 2,
              "base_coin": "etc",
              "price_precision": 8
          }
      ]
  }
      

Get tickers in all available markets

  1. Endpoint URL: /v1/ticker
  2. Method: GET
  3. Description: gets all trading pairs quotes on the market.
  4. This is a public interface, request signature is not needed
  5. Request Parameter: no parameter is allowed
  6. Response Content-Type: application/json
  7. Response JSON fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
    "date": 1534335607859, // Server time 
    "ticker": [
      {
        "symbol": "btcusdt", // Transaction pairs 
        "high": "9744.47", // Highest price in the last 24 hours
        "vol": "0.0251263", // Trading volume in the last 24 hours
        "last": 9744.2500000000000000 , // Latest transaction price
        "low": "9744.25", // Lowest price in the last 24 hours
        "buy": 9744.25, // Current buy price
        "sell": 9744.47, // Current sell price
        "change": "-0.0000225769", // 
        "rose": "-0.0000225769" // ups or downs
      },
      {
        "symbol": "ethusdt",
        "high": 535.96,
        "vol": 6366.8591,
        "last": 20,
        "low": 279.57,
        "rose": -0.44564773
      },
      {
        "symbol": "ethbtc",
        "high": 1,
        "vol": 281261,
        "last": 0.1,
        "low": 0.044039,
        "buy": "0.044049",
        "sell": "0.044049",
        "rose": -0.00022701
      }
    ]
  }
      

Get ticker for a particular market

  1. Endpoint URL: /v1/ticker
  2. Method: GET
  3. Description: gets the current market quotes.
  4. This is a public interface, request signature is not needed
  5. Request Parameters: see below
Request Parameter Required Description
symbol Yes Market mark, btcusdt, See below for details
  1. Response Content-Type: application/json
  2. Response JSON fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "high": 1, //Maximum value
      "vol": 10232.26315789, //Trading volume
      "last": 173.60263169, //Latest Transaction Price
      "low": 0.01, //Minimum value
      "buy": "0.01000000", //Buy one price
      "sell": "1.12345680", //Selling price
      "rose": -0.44564773, //Ups and downs
      "time": 1514448473626
  }
      

Get k-line data over a specified period

  1. Endpoint URL: /v1/klines
  2. Method: GET
  3. Description: gets K-line data.
  4. This is a public interface, request signature is not needed
  5. Request Parameter: no parameter is allowed
Get Parameter Required Description
period Yes Given in minutes. Possible values are [1, 5, 15, 30, 60, 1440, 10080, 43200]<br>which corresponds to 1min, 5min, 15min, 30min, 1hour, 1day, 1week, 1month.
symbol Yes Market mark, bchbtc, See below for details
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
[
    [
      1514445780,  //time stamp
      1.12,        //Opening price
      1.12,        //Highest
      1.12,        //minimum
      1.12,        //Closing price
      0            //volume
    ],
    [
      1514445840,
      1.12,
      1.12,
      1.12,
      1.12,
      0
    ],
    [
      1514445900,
      1.12,
      1.12,
      1.12,
      1.12,
      0
    ]
  ]
      

Get last 200 trades in a specified market

  1. Endpoint URL: /v1/trades
  2. Method: GET
  3. Description: obtains market transaction records.
  4. This is a public interface, request signature is not needed
  5. Request Parameter: see below
GET Parameter Required Description
symbol Yes Market mark, bchbtc, See below for details
  1. Response Content-Type: application/json
  2. Response JSON fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
    "code": "0",
    "msg": "suc",
    "data": [
      {
          "amount": 0.0010000000000000,
          "price": 9744.2500000000000000,
          "ctime": 1572404045000,
          "id": 6303,
          "type": "sell"
      },
      {
          "amount": 0.0000010200000000,
          "price": 9744.4700000000000000,
          "ctime": 1572404025000,
          "id": 6302,
          "type": "buy"
      },
      {
          "amount": 0.0010000000000000,
          "price": 9744.2500000000000000,
          "ctime": 1572403679000,
          "id": 6301,
          "type": "sell"
      },
      {
          "amount": 0.0010000000000000,
          "price": 9744.2500000000000000,
          "ctime": 1572403679000,
          "id": 6300,
          "type": "sell"
      }
    ]
  }
      

Get latest execution price for all markets

  1. Endpoint URL: /v1/ticker/price
  2. Method: GET
  3. Description: gets the latest transaction price of each pair of currencies.
  4. This is a public interface, request signature is not needed
  5. Request Parameter: no parameter is allowed
  6. Response Content-Type: application/json
  7. Response JSON Fields: see below
Response JSON Field Example Description
code 0
msg "suc" Success or failure
data {"btcusdt":15000,"ethusdt":800}

Get the order book for a particular market

  1. Endpoint URL: /v1/depth
  2. Method: GET
  3. Description: gets the list of orders from buyers and sellers for the market
  4. This is a public interface, request signature is not needed
  5. Request Parameter: see below
Get Parameter Required Description
symbol Yes Market mark, ethbtc, See below for details
type Yes The depth type -- options: step0, step1, step2 (Merger depth0-2). step0 has the highest accuracy
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "tick": {
          "asks": [
            [
              9745,
              0.57373498
            ],
            [
              9748,
              0.25
            ],
          ],
          "bids": [
            [
              9744,
              102.45305246
            ],
            [
              9654,
              1.831
            ],
          ],
          "time": null
      }
  }
      

User API

List all account balance of user

  1. Endpoint URL: /v1/account
  2. Method: POST
  3. Description: display the balance of user’s assets across all accounts
  4. Request Parameter: see below
POST Parameter Required Description
api_key Yes API key
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
    "total_asset": 432323.23, // user total assets (estimated in BTC)
    "coin_list": [
      {
        "normal": 32323.233, // usable balance
        "locked": 32323.233, // locked balance, e.g. locked in an active, non-executed order
        "btcValuatin": 112.33, // value equal to BTC
        "coin": "btc" // asset type
      },
      {
        "normal": 32323.233,
        "locked": 32323.233,
        "btcValuatin": 112.33,
        "coin": "ltc"
      },
      {
        "normal": 32323.233,
        "locked": 32323.233,
        "btcValuatin": 112.33,
        "coin": "bch"
      }
    ]
  }
      

Create an order

  1. Endpoint URL: /v1/order
  2. Method: POST
  3. Description: creates a buy or sell order on exchange
  4. Request Parameter: see below
POST parameter Required Description
api_key Yes API key
fee_is_user_exchange_coin No (Redundant fields are ignored) this parameter indicates whether to use the platform currency to pay the handling fee, 0 means no, 1 means yes. 0 when the exchange has the platform currency.
price No Authorized unit price. If type=2 then no need for this parameter.
side Yes BUY, SELL
symbol Yes Market symbol “ethbtc”
time Yes Time stamp
type Yes Type of list: 1 for limit order (user sets a price), 2 for market order (best available price)
volume Yes Purchase quantity (Polysemy, multiplexing fields) <br>type=1 represents the quantity of sales and purchases<br>type=2: buy means the total price, Selling represents the total number.<br>Trading restrictions user/me-User information.
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "order_id": 34343 // the newly created order_id
  }
      

Get order detail

  1. Endpoint URL: /v1/showOrder
  2. Method: POST
  3. Description: obtain order details.
  4. Request Parameter: see below
POST Parameter Required Description
api_key Yes API key
order_id Yes Order ID
symbol Yes Market symbol “ethbtc”, See below for details
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "trade_list": [
          {
              "volume": "0.00100000",
              "feeCoin": "USDT",
              "price": "9744.25000000",
              "fee": "0.00000000",
              "ctime": 1571971998000,
              "deal_price": "9.74425000",
              "id": 6224,
              "type": "SELL"
          }
      ],
      "order_info": {
          "id": 8140,
          "side": "SELL",
          "total_price": "8.00000000",
          "fee": 0E-8,
          "created_at": 1571971998681,
          "deal_price": 9.7442500000000000,
          "avg_price": "9744.25000000",
          "countCoin": "USDT",
          "source": 3,
          "type": 1,
          "side_msg": "SELL",
          "volume": "0.00100000",
          "price": "8000.00000000",
          "source_msg": "API",
          "status_msg": "Completely Filled",
          "deal_volume": "0.00100000",
          "fee_coin": "USDT",
          "remain_volume": "0.00000000",
          "baseCoin": "BTC",
          "tradeList": [
              {
                  "volume": "0.00100000",
                  "feeCoin": "USDT",
                  "price": "9744.25000000",
                  "fee": "0.00000000",
                  "ctime": 1571971998000,
                  "deal_price": "9.74425000",
                  "id": 6224,
                  "type": "SELL"
              }
          ],
          "status": 2
      }
  }
      

Cancel an order

  1. Endpoint URL: /v1/orders/cancel
  2. Method: POST
  3. Description: cancellation of the order.
  4. Request Parameter: see below
POST body Parameter Required Description
api_key Yes API key
order_id Yes OrderID
symbol Yes Market symbol "ethbtc". See below for details
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data (null)

Cancel all orders in a particular market

  1. Endpoint URL: /v1/cancelAllOrders
  2. Method: POST
  3. Description: cancellation of all orders according to currency pair (Up to 2,000 cancellations).
  4. Request Parameter: see below
POST Parameter Required Description
symbol Yes Market symbol "ethbtc", See below for details
api_key Yes API key
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data (null)

List all open orders in a particular market

  1. Endpoint URL: /v1/openOrders
  2. Method: POST
  3. Description: get the current pending orders
  4. Request Parameter: see below
POST Parameter Required Description
api_key Yes API key
page No Page number
pageSize No Page size
symbol Yes Market symbol "btcusdt", See below for details
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "count":10,
      "resultList":[
          {
              "side": "BUY",
              "total_price": "9.00000000",
              "fee": 0E-8,
              "created_at": 1571971994609,
              "deal_price": 0E-16,
              "avg_price": "0.00000000",
              "countCoin": "USDT",
              "source": 3,
              "type": 1,
              "side_msg": "BUY",
              "volume": "0.00100000",
              "price": "9000.00000000",
              "source_msg": "API",
              "status_msg": "Unsettled",
              "deal_volume": "0.00000000",
              "fee_coin": "BTC",
              "id": 8139,
              "remain_volume": "0.00100000",
              "baseCoin": "BTC",
              // 0: INIT, "Initial order"
              // 1: NEW, "New order, Unfinished business enters the market"
              // 2: FILLED, "Full deal"
              // 3: PART_FILLED, "Partial transaction"
              // 4: CANCELED, "Order cancelled"
              // 5: PENDING_CANCEL, "Order will be cancelled"
              // 6. EXPIRED(, "Abnormal order"
              "status": 1
          },
          {
              "side": "BUY",
              "total_price": "9.00000000",
              "fee": 0E-8,
              "created_at": 1571880796540,
              "deal_price": 0E-16,
              "avg_price": "0.00000000",
              "countCoin": "USDT",
              "source": 3,
              "type": 1,
              "side_msg": "BUY",
              "volume": "0.00100000",
              "price": "9000.00000000",
              "source_msg": "API",
              "status_msg": "Unsettled",
              "deal_volume": "0.00000000",
              "fee_coin": "BTC",
              "id": 8081,
              "remain_volume": "0.00100000",
              "baseCoin": "BTC",
              "status": 1
          }
      ]
  }
      

List all orders in a particular market

  1. Endpoint URL: /v1/allOrders

  2. Method: POST

  3. Description: acquire full list of orders (including executed, pending, cancelled orders)

  4. Request Parameter: see below

POST Parameter Required Description
api_key Yes API key
endDate No (Added) End time, accurate to seconds "yyyy-MM-dd HH:mm:ss"
page No Page number
pageSize No Page size
startDate No (Added) Start time, accurate to seconds "yyyy-MM-dd HH:mm:ss"
symbol Yes Market symbol "btcusdt", See below for details
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "count":10,
      "orderList":[
          {
              "side": "BUY",
              "total_price": "9.74447000",
              "fee": 0E-8,
              "created_at": 1572235997622,
              "deal_price": 9.7444700000000000,
              "avg_price": "9744.47000000",
              "countCoin": "USDT",
              "source": 1,
              "type": 1,
              "side_msg": "BUY",
              "volume": "0.00100000",
              "price": "9744.47000000",
              "source_msg": "WEB",
              "status_msg": "Completely Filled",
              "deal_volume": "0.00100000",
              "fee_coin": "BTC",
              "id": 8145,
              "remain_volume": "0.00000000",
              "baseCoin": "BTC",
              "status": 2
          },
          {
              "side": "SELL",
              "total_price": "8.00000000",
              "fee": 0E-8,
              "created_at": 1571971998681,
              "deal_price": 9.7442500000000000,
              "avg_price": "9744.25000000",
              "countCoin": "USDT",
              "source": 3,
              "type": 1,
              "side_msg": "SELL",
              "volume": "0.00100000",
              "price": "8000.00000000",
              "source_msg": "API",
              "status_msg": "Completely Filled",
              "deal_volume": "0.00100000",
              "fee_coin": "USDT",
              "id": 8140,
              "remain_volume": "0.00000000",
              "baseCoin": "BTC",
              "status": 2
          },
      ]
  }
      

List all executed orders

  1. Endpoint URL: /v1/myTrades
  2. Method: POST
  3. Description: get all records of executed orders
  4. Request Parameter: see below
POST Parameter Required Description
api_key Yes API key
endDate No (Added) End time, accurate to seconds "yyyy-MM-dd HH:mm:ss"
page No Page number
pageSize No Page size
startDate No (Added) Start time, accurate to seconds "yyyy-MM-dd HH:mm:ss"
symbol Yes Market symbol "btcusdt", See below for details
time Yes Time stamp
sign Yes sha256 signature
  1. Response Content-Type: application/json
  2. Response JSON Fields: see below
Response JSON Field Example Description
code 0 Return code, 0 for success, non-zero for failure
msg "suc" Success or the error message
data shown below
{
      "count":100,
      "resultList":[
          {
              "volume": "0.00100000",
              "side": "BUY",
              "feeCoin": "BTC",
              "price": "9744.47000000",
              "fee": "0.00000000",
              "ctime": 1572235997000,
              "deal_price": "9.74",
              "id": 6227,
              "type": "BUY",
              "bid_id": 8145,
              "bid_user_id": 10106
          },
          {
              "volume": "0.001",
              "side": "SELL",
              "feeCoin": "USDT",
              "ask_user_id": 10106,
              "price": "9744.25000000",
              "fee": "0.00000000",
              "ctime": 1571971998000,
              "deal_price": "9.74",
              "id": 6224,
              "type": "SELL",
              "ask_id": 8140
          }
      ]
  }
      

WebSocket API

Request current tickers in all available markets

{"event":"req","params":{"channel":"review"}}
                          
{
      event_rep: "rep",
      channel: "review",
      data: {
              bchbtc:  {amount: "115.968833484"close: "0.07956"high: "0.086323"low: "0.079251"open: "0.086323"rose: "-0.07834528"vol: "1393.247"}
              bchusdt: {amount: "416316.164145661", close: "513.56", high: "556.42", low: "510.85", open: "555.71", ...}
              btcusdt: {amount: "999341.34124", close: "6450.18", high: "6486.39", low: "6359.63", open: "6435.79", ...}
      }
  }
      

Subscribe to new tickers for a particular market

{"event":"sub","params":{"channel":"market_${symbol}_ticker" }}
                          
{
      "event_rep":"",
      "channel":"market_${symbol}_ticker",
      "ts":1506584998239,
      "status":"ok",
      "lower_frame":"0" // lower_frame: 0 No coin pair off the shelf,  1 Coin pair
  }
      
{
      "channel":"market_${symbol}_ticker", //Subscription transactions versus market${symbol} crobtc etc.
      "ts":1506584998239, //d time
      "tick":{
          "id":1506584998, //Redundancy, no practical significance, timestamp
          "amount":123.1221, //A turnover
          "vol":1212.12211, //Trading volume
          "open":2233.22, //Opening price
          "close":1221.11, //Closing price
          "high":22322.22, //Highest price
          "low":2321.22, //Minimum price
          "rose":-0.2922, //Gain
          "ts":1506584998239, //Data generation time
          "lower_frame":"0"
      }
  }
      

Request k-line data history over a specified period

{
      "event":"req",
      "params":{
          "channel":"market_${symbol}_kline_[1min/5min/15min/30min/60min/1day/1week/1month]",
          "since":"1506602880"
      }
  }
      
{
      "event_rep":"rep","channel":"market_${symbol}_kline_[1min/5min/15min/30min/60min/1day/1week/1month]"
      "since":"1506602880",
      "ts":1506584998239, //Request time
      "data":[ //300 article
          {
              "id":1506602880, //Time scale starting value
              "amount":123.1221, //A turnover
              "vol":1212.12211, //Trading volume
              "open":2233.22, //Opening price
              "close":1221.11, //Closing price
              "high":22322.22, //Highest price
              "low":2321.22 //Minimum price
          },
          {
              "id":1506602880, //Time scale starting value
              "amount":123.1221, //A turnover
              "vol":1212.12211, //Trading volume
              "open":2233.22, //Opening price
              "close":1221.11, //Closing price
              "high":22322.22, //Highest price
              "low":2321.22 //Minimum price
          }
      ]
  }
      

Subscribe to new k-line data over a specified period

{
      "event":"sub",
      "params":{
          "channel":"market_${symbol}_kline_[1min/5min/15min/30min/60min/1day/1week/1month]"

      }
  }
      
{
      "event_rep":"",
      "channel":"market_${symbol}_kline_[1min/5min/15min/30min/60min/1day/1week/1month]",
      "ts":1506584998239,"status":"ok"
  }
      
{
      "channel":"market_${symbol}_kline_[1min/5min/15min/30min/60min/1day/1week/1month]", //Subscription transactions versus market${symbol} crobtc etc.

      "ts":1506584998239, //Request time
      "tick":{
          "id":1506602880, //Time scale starting value
          "amount":123.1221, //A turnover
          "vol":1212.12211, //Trading volume
          "open":2233.22, //Opening price
          "close":1221.11, //Closing price
          "high":22322.22, //Highest price
          "low":2321.22 //Minimum price
      }
  }
      

Request last 200 trades in a specified market

{
      "event":"req",
      "params":{
          "channel":"market_${symbol}_trade_ticker",
          "top":200
      }
  }
      
{
      "event_rep":"rep",
      "channel":"market_${symbol}_trade_ticker",
      "ts":1506584998239,
      "status":"ok",
      "top":200, //Maximum support 200
      "data":[
          {
              "id":12121, //Transaction ID
              "side":"buy", //Direction of businessbuy,sell
              "price":32.233, //Unit Price
              "vol":232, //Number
              "amount":323, //Total
              "ts":1506584998239 //Data generation time
          },
          {
              "id":12120, //Transaction ID
              "side":"buy", //Direction of business buy,sell
              "price":32.233, //Unit Price
              "vol":232, //Number
              "amount":323, //Total
              "ts":1506584998239, //Data generation time
              "ds":'2017-09-10 23:12:21'
          }
      ]
  }
      

Subscribe to new trades in a specified market

{
      "event":"sub",
      "params":{
          "channel":"market_${symbol}_trade_ticker"
      }
  }
      
{
      "event_rep":"",
      "channel":"market_${symbol}_trade_ticker",
      "ts":1506584998239,
      "status":"ok"
  }
      
{
      "channel":"market_${symbol}_trade_ticker", //Subscription transactions versus market${symbol} crobtc etc.
      "ts":1506584998239, //Request time
      "tick":{
          "id":12121, //dataThe biggest deal ID
          "ts":1506584998239, //dataThe biggest deal
          "data":[
              {
                  "id":12121, //transaction ID
                  "side":"buy", //Direction of business buy,sell
                  "price":32.233, //Unit Price
                  "vol":232, //Number
                  "amount":323, //Total
                  "ts":1506584998239, //Data generation time
                  "ds":'2017-09-10 23:12:21'
              },
              {
                  "id":12120, //Transaction ID
                  "side":"buy", //Direction of business buy,sell
                  "price":32.233, //Unit Price
                  "vol":232, //Number
                  "amount":323, //Total
                  "ts":1506584998239, //Data generation time
                  "ds":'2017-09-10 23:12:21'
              }
          ]
      }
  }
      

Subscribe to order book for a particular market (Full update)

{
      "event":"sub",
      "params":{
          "channel":"market_${symbol}_depth_step[0-2]",
          "asks":150,
          "bids":150
      }
  }
      
{
      "event_rep":"",
      "channel":"market_${symbol}_depth_step[0-2]",
      "asks":150,
      "bids":150,
      "ts":1506584998239,
      "status":"ok"
  }
      
{
      "channel":"market_${symbol}_depth_step[0-2]", //${symbol} crobtc etc.,Depth has 3 dimensions, 0, 1, 2
      "ts":1506584998239, //Request time
      "tick":{
          "asks":[ //Selling
              [22112.22,0.9332],
              [22112.21,0.2]
          ],
          "buys":[ //Bid
              [22111.22,0.9332],
              [22111.21,0.2]
          ]
      }
  }
      

API Examples

All sample code is provided for illustrative purposes only. These examples have not been thoroughly tested under all conditions. We, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you “AS IS” without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.

Java Example - WebSocket API


  package test;

  import javax.net.ssl.SSLContext;
  import javax.net.ssl.TrustManager;
  import javax.net.ssl.X509TrustManager;
  import javax.websocket.*;
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.EOFException;
  import java.io.IOException;
  import java.net.URI;
  import java.nio.ByteBuffer;
  import java.nio.CharBuffer;
  import java.nio.charset.Charset;
  import java.nio.charset.CharsetDecoder;
  import java.nio.charset.StandardCharsets;
  import java.security.cert.CertificateException;
  import java.security.cert.X509Certificate;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.zip.GZIPInputStream;

  public class WsTest {

      public static void main(String[] args) {
          try {
              //wsurl
              String url = "wss://ws.crypto.com/kline-api/ws";
              //Historical data request parameters
              String reqParam = '{"event":"req","params":{"channel":"market_btcusdt_trade_ticker","top":150}}';

              //Subscription parameters
              String subParam = '{"event":"sub","params":{"channel":"market_btcusdt_depth_step0","asks":20, "bids":20}}';

              // Send Parameters
              final WebSocketUtils webSocketUtils = WebSocketUtils.executeWebSocket(url, subParam);

              //Thread does not end, waiting for new messages, www.crypto.com Generally, a new deal will return in about a minute
              while (webSocketUtils.isOpen()) {
                  Thread.sleep(2000);
                  System.out.println("Cycle");
              }

          } catch (Exception e) {
              e.printStackTrace();
          }
      }

      @ClientEndpoint
      public static class WebSocketUtils {
          private static WebSocketContainer wsclient = null;
          private String starterMsg = "";
          Session userSession;

          @OnOpen
          public void onOpen(Session userSession) throws IOException {
              System.out.println("Links have been established");
              this.userSession = userSession;
              sendMessage(starterMsg);
          }

          @OnMessage
          public void onMessage(String s) {
              System.out.println("Receive a string message " + s);
          }

          @OnClose
          public void onClose(Session userSession, CloseReason reason) {
              System.out.println("Link closed " + reason.getCloseCode() + ":" + reason.getReasonPhrase());
          }

          public void sendMessage(String message) {
              System.out.println("Sending Message: " + message);
              try {
                  if (isOpen()) {
                      userSession.getBasicRemote().sendText(message);
                  }
              } catch (IOException e1) {
                  System.out.println("Error: Trouble sending message" + e1);
              }
          }

          boolean isOpen() {
              return userSession.isOpen();
          }

          @OnMessage
          public void onMessage(ByteBuffer socketBuffer) {
              System.out.println("Received a buffer");
              try {
                  String marketStr = byteBufferToString(socketBuffer);
                  String market = uncompress(marketStr).toLowerCase();
                  if (market.contains("ping")) {
                      System.out.println("Receive messageping: " + market);
                      String tmp = market.replace("ping", "pong");
                      sendMessage(market.replace("ping", "pong"));
                  } else {
                      System.out.println("Received message: " + market);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }

          public static Map getWebSocketHeaders() throws IOException {
              Map headers = new HashMap();
              return headers;
          }

          public static WebSocketUtils executeWebSocket(String url, String sendMsg) throws Exception {
              WebSocketUtils utils = new WebSocketUtils();
              utils.wsclient = ContainerProvider.getWebSocketContainer();
              utils.starterMsg = sendMsg;
              utils.wsclient.connectToServer(utils, new URI(url));
              return utils;
          }

          // buffer turn String
          public String byteBufferToString(ByteBuffer buffer) {
              CharBuffer charBuffer;
              try {
                  Charset charset = StandardCharsets.ISO_8859_1;
                  CharsetDecoder decoder = charset.newDecoder();
                  charBuffer = decoder.decode(buffer);
                  buffer.flip();
                  return charBuffer.toString();
              } catch (Exception ex) {
                  ex.printStackTrace();
                  return null;
              }
          }

          // decompression
          public String uncompress(String str) throws IOException {
              if (str == null || str.length() == 0) {
                  return str;
              }
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
              GZIPInputStream gunzip = new GZIPInputStream(in);
              byte[] buffer = new byte[256];
              int n;
              while ((n = gunzip.read(buffer)) >= 0) {
                  out.write(buffer, 0, n);
              }
              return out.toString();
          }

      }
  } // class


      

Node JS Example - User API


  var request         = require("request");
  var SHA256          = require("crypto-js/sha256");
  var formurlencoded  = require('form-urlencoded').default;

  params              = {};
  params["api_key"]   = "API_KEY"; // to replace by real API key => better to get as input and encrypt with shared secret input 
  params["time"]      = new Date().getTime();;
  var secret_key      = "SECRET_KEY"; // to replace by real secret key => => better to get as input and encrypt with shared secret input 
  var apiUrl          = "https://api.crypto.com/v1/";

  console.log("params: " + JSON.stringify(params));
  var messageNotEncoded = "";

  for(var key in params) {
      messageNotEncoded += key;
      messageNotEncoded += params[key];
  }
  messageNotEncoded   += secret_key;

  var sign = SHA256(messageNotEncoded).toString();
  console.log("Encoded message: " + sign);

  params["sign"] = sign;
  console.log("params: " + JSON.stringify(params));

  var formParams  = {"form": formurlencoded(params)};
  var apiCallPath = "account";
  var postUrl     = apiUrl + apiCallPath;
  console.log("Post URL: " + postUrl);
  console.log("Post Form: " + JSON.stringify(formParams));

  request.post(postUrl, formParams, function(error, response) {
      if(!error) {
          console.log(response.body)    
          var responseJson = JSON.parse(response.body);
          console.log(responseJson["msg"]);
          console.log(responseJson["data"]);
      }
  });
      

Node JS Example - WebSocket API


  const WebSocket = require('ws');
  // For zlib decompression of Websocket data
  const pako = require('pako');
  var counter = 0;
  const wss = new WebSocket('wss://ws.crypto.com/kline-api/ws', {
      perMessageDeflate: true
  });
  wss.on('open', function open() {
      console.log('-----------------');
      console.log('Connection OPENED');
      console.log('-----------------');
      // Test subscribe
      var msg = '{"event":"sub","params":{"channel":"market_btcusdt_trade_ticker"}}';
      wss.send(msg);
  });
  wss.on('message', function incoming(data) {
      // zlib decompression of binary data
      var inflated = pako.inflate(data, { to: 'string' });
      console.log(counter + ': ' + inflated);
      // Test UNsubscribe
      if (inflated.indexOf('event_rep') >= 0) {
          counter++;
          // If the count of ticker data exceeds 3 or more, then UNsubscribe
          if (counter >= 3) {
              var msg = '{"event":"unsub","params":{"channel":"market_btcusdt_trade_ticker"}}';
              wss.send(msg);    
          }
      }
  });
  wss.on('close', function close() {
      console.log('-----------------');
      console.log('Connection CLOSED');
      console.log('-----------------');
  });
  wss.on('error', function error(e) {
      console.log('-----------------');
      console.log('*** ERROR *** ' + e);
      console.log('-----------------');
  });
      

Python Example - User API

Requirements: Python 3.6 or above, pip install requests


  # Modify your API and SECRET keys here:
  API_KEY = "API_KEY"
  SECRET_KEY = "SECRET_KEY"
  API_ENDPOINT = "https://api.crypto.com/v1/account"
  import hashlib
  import json
  import requests
  import time
  params = {}
  params['api_key'] = API_KEY
  params['time'] = int(time.time() * 1000)
  messageNotEncoded = ""
  for key in params:
      messageNotEncoded += key
      messageNotEncoded += str(params[key])
  messageNotEncoded += SECRET_KEY
  #print("Decoded Message: " + messageNotEncoded)
  sign = hashlib.sha256(messageNotEncoded.encode('utf-8')).hexdigest()
  print("Encoded Message: " + sign)
  params['sign'] = sign
  postUrl = API_ENDPOINT
  print("Post URL: " + postUrl)
  print("Post Form: " + json.dumps(params))
  try:
      response = requests.post(url = postUrl, data = params)
      print ("Response: " + str(response.content))
      response.raise_for_status()
  except requests.exceptions.HTTPError as err_h:
      print (f'*** HTTP ERROR *** {err_h}')
  except requests.exceptions.ConnectionError as err_c:
      print (f'*** CONNECTION ERROR *** {err_c}')
  except requests.exceptions.Timeout as err_t:
      print (f'*** TIMEOUT ERROR *** {err_t}')   
  except requests.exceptions.RequestException as e:
      print (f'*** OTHER ERROR *** {e}')
      

Python Example - Market and User API


  import urllib
  import requests
  import hashlib
  import time


  def get_timestamp():
      ts = "%d"%int(round(time.time() * 1000))
      return ts


  class CryptoAPI:
      def __init__(self, key, sec):
          self.timeout = 1000
          self.apiurl = "https://api.crypto.com"
          self.apikey = key
          self.apisec = sec
          return

      def http_get(self, url, params):
          headers = {
              'Content-Type': "application/x-www-form-urlencoded"
          }
          data = urllib.urlencode(params or {})
          try:
              response = requests.get(url, data, headers=headers, timeout=self.timeout)
              if response.status_code == 200:
                  return response.json()
              else:
                  return {"code": -1, "msg": "response status:%s" % response.status_code}
          except Exception as e:
              print("httpGet failed, detail is:%s" % e)
              return {"code": -1, "msg": e}

      def http_post(self, url, params):
          headers = {
              "Content-type": "application/x-www-form-urlencoded",
          }
          data = urllib.urlencode(params or {})
          try:
              response = requests.post(url, data, headers=headers, timeout=self.timeout)
              if response.status_code == 200:
                  return response.json()
              else:
                  return {"code": -1, "msg": "response status:%s" % response.status_code}
          except Exception as e:
              print("httpPost failed, detail is:%s" % e)
              return {"code": -1, "msg": e}

      def api_key_get(self, url, params):
          if not params:
              params = {}
          params["api_key"] = self.apikey
          params["time"] = get_timestamp()
          params["sign"] = self.create_sign(params)
          return self.http_get(url, params)

      def api_key_post(self, url, params):
          if not params:
              params = {}
          params["api_key"] = self.apikey
          params["time"] = get_timestamp()
          params["sign"] = self.create_sign(params)
          return self.http_post(url, params)

      def create_sign(self, params):
          sorted_params = sorted(params.items(), key=lambda d: d[0], reverse=False)
          s = "".join(map(lambda x: str(x[0]) + str(x[1] or ""), sorted_params)) + self.apisec
          h = hashlib.sha256(s)
          return h.hexdigest()

      def depth(self, sym):
          url = self.apiurl + "/v1/depth"
          params = {"symbol": sym,
                    "type": "step0"}
          return self.http_get(url, params)

      def balance(self):
          url = self.apiurl + "/v1/account"
          return self.api_key_post(url, {})

      def get_all_orders(self, sym):
          url = self.apiurl + "/v1/allOrders"
          params = {}
          params['symbol'] = sym
          return self.api_key_post(url, params)

      def get_order(self, sym, oid):
          url = self.apiurl + "/v1/showOrder"
          params = {}
          params['order_id'] = oid
          params['symbol'] = sym
          return self.api_key_post(url, params)

      def get_ordst(self, sym, oid):
          url = self.apiurl + "/v1/showOrder"
          params = {}
          params['order_id'] = oid
          params['symbol'] = sym
          res = self.api_key_post(url, params)
          if ('code' in res) and (res['code']=='0') and ('order_info' in res['data']):
              return res['data']['order_info']['status']
          return -1

      def get_open_orders(self, sym):
          url = self.apiurl + "/v1/openOrders"
          params = {}
          params['pageSize'] = '200'
          params['symbol'] = sym
          return self.api_key_post(url, params)

      def get_trades(self, sym):
          url = self.apiurl + "/v1/myTrades"
          params = {}
          params['symbol'] = sym
          return self.api_key_post(url, params)

      def cancel_order(self, sym, oid):
          url = self.apiurl + "/v1/orders/cancel"
          params = {}
          params['order_id'] = oid       
          params['symbol'] = sym
          return self.api_key_post(url, params)

      def cancel_order_all(self, sym):
          url = self.apiurl + "/v1/cancelAllOrders"
          params = {}
          params['symbol'] = sym
          return self.api_key_post(url, params)


      def create_order(self, sym, side, prx, qty):
          """
              s:return:
          """
          url = self.apiurl + "/v1/order"
          params = {}
          params['price'] = prx
          params['side'] = side
          params['symbol'] = sym      
          params['type'] = 1
          params['volume'] = qty
          return self.api_key_post(url, params)
              


      

C# Example - Market, User APIs



  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Net;
  using System.Security.Cryptography;
  using System.Text;
  using System.Threading.Tasks;
  using System.Web;
  using System.Net.WebSockets;


  public class Sample
  {
      private const string API_KEY = "YOUR_API_KEY";
      private const string API_SECRET = "YOUR_API_SECRET";
      private const string API_URL = "https://api.crypto.com";

      public static void Main(string[] args)
      {
          // Market APIs
          //GetMarketSymbols();
          //GetTicker();
          //GetTicker("btcusdt");
          //GetKlineData(1440, "btcusdt");
          //GetLast200Trades("btcusdt");
          //GetLastExecutionPrices();
          //GetOrderBook("btcusdt", "step0");

          // User APIs
          //GetAccountBalance();
          //CreateOrder (0, 80, "BUY", "mcocro", 1, 1);
          //GetOrderDetails ("4340499", "mcocro");
          //CancelOrder ("4340499", "mcocro");
          //CancelAllOrders ("mcocro");
          //GetPendingOrders (1, 10, "mcocro");
          //GetAllOrders ("2020-01-01 00:00:00", "2020-01-31 23:59:59", 1, 100, "mcocro");
          //GetExecutedOrders ("2020-01-01 00:00:00", "2020-01-31 23:59:59", 1, 100, "mcocro");
      }

      /*
      -----------
      MARKET APIS
      -----------
      */  
      public static void GetMarketSymbols ()
      {
          var Response = CallEndpoint ("GET", "/v1/symbols");
      }

      public static void GetTicker (dynamic Symbol = null)
      {
          dynamic Params = null;

          if (Symbol != null) 
          {
              Params = InitializeDictionary();
              Params.Add ("symbol", Symbol);
          }

          var Response = CallEndpoint ("GET", "/v1/ticker", Params);
      }

      public static void GetKlineData (int Period, string Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("period", Period);
          Params.Add ("symbol", Symbol);
          var Response = CallEndpoint ("GET", "/v1/klines", Params);
      }

      public static void GetLast200Trades (string Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("symbol", Symbol);
          var Response = CallEndpoint ("GET", "/v1/trades", Params);
      }

      public static void GetLastExecutionPrices ()
      {
          var Response = CallEndpoint ("GET", "/v1/ticker/price");
      }

      public static void GetOrderBook (string Symbol, string Type)
      {
          var Params = InitializeDictionary();
          Params.Add ("symbol", Symbol);
          Params.Add ("type", Type);
          var Response = CallEndpoint ("GET", "/v1/depth", Params);
      }


      /*
      ---------
      USER APIS
      ---------
      */  
      public static void GetAccountBalance ()
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/account", Params);
      }    
      
      public static void CreateOrder (int UsePlatformTokenForFees, float Price, string Side, String Symbol, int OrderType, int Volume)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);

          if (UsePlatformTokenForFees == 1) 
          {
              Params.Add ("fee_is_user_exchange_coin", UsePlatformTokenForFees);
          }

          Params.Add ("price", Price);
          Params.Add ("side", Side);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("type", OrderType);
          Params.Add ("volume", Volume);
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/order", Params);
      }

      public static void GetOrderDetails (dynamic OrderId, String Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("order_id", OrderId);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/showOrder", Params);
      }

      public static void CancelOrder (dynamic OrderId, String Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("order_id", OrderId);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/orders/cancel", Params);
      }

      public static void CancelAllOrders (String Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/cancelAllOrders", Params);
      }

      public static void GetPendingOrders (int PageNumber, int PageSize, String Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("page", PageNumber);
          Params.Add ("pageSize", PageSize);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/openOrders", Params);
      }

      public static void GetAllOrders (string StartDate, string EndDate, int PageNumber, int PageSize, String Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("endDate", EndDate);
          Params.Add ("page", PageNumber);
          Params.Add ("pageSize", PageSize);
          Params.Add ("startDate", StartDate);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/allOrders", Params);
      }    

      public static void GetExecutedOrders (string StartDate, string EndDate, int PageNumber, int PageSize, String Symbol)
      {
          var Params = InitializeDictionary();
          Params.Add ("api_key", API_KEY);
          Params.Add ("endDate", EndDate);
          Params.Add ("page", PageNumber);
          Params.Add ("pageSize", PageSize);
          Params.Add ("startDate", StartDate);
          Params.Add ("symbol", Symbol);
          Params.Add ("time", GetTimestamp());
          Params.Add ("sign", GetSign(Params));

          var Response = CallEndpoint ("POST", "/v1/myTrades", Params);
      }       


      /*
      ----------------
      COMMON FUNCTIONS
      ----------------
      */  
      private static string GetTimestamp () 
      {
          // Calculate UTC Unix Timestamp
          return (string)Math.Floor((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds * 1000).ToString();
      }

      private static string GetSign (Dictionary Params)
      {
          // Join all Params together, combining key with value        
          string RawMessage = string.Join("", Params.Select(entry => $"{entry.Key}{entry.Value}")) + API_SECRET;

          // Create the 'sign' using SHA256; ensure encoding is in UTF8
          byte[] MessageBytes = Encoding.UTF8.GetBytes(RawMessage);
          byte[] HashMessage  = SHA256.Create().ComputeHash(MessageBytes, 0, MessageBytes.Length);
          return String.Concat(Array.ConvertAll(HashMessage, x => x.ToString("x2")));
      }

      private static string CallEndpoint (String Method, String EndPoint, Dictionary Params = null) 
      {           
          HttpWebRequest Request;

          string Url = API_URL + EndPoint;

          // Set TLS to 1.2
          ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

          if (Params != null && Params.Count > 0) 
          {
              string ParamString = string.Join("&", Params.Select(entry => $"{entry.Key}={entry.Value}"));

              // For debugging
              Console.WriteLine($"ParamString: {ParamString}");

              if (Method == "POST")
              { 
                  
                  Request = (HttpWebRequest) WebRequest.Create(Url);

                  Request.Method = Method;
                  
                  var ByteData = Encoding.ASCII.GetBytes(ParamString);

                  Request.ContentType = "application/x-www-form-urlencoded";
                  Request.ContentLength = ByteData.Length;

                  using (var Stream = Request.GetRequestStream())
                  {
                      Stream.Write(ByteData, 0, ByteData.Length);
                  }            
              }
              else
              {
                  Url = Url + '?' + ParamString;

                  Request = (HttpWebRequest) WebRequest.Create(Url);

                  Request.Method = Method;
              }
          } else {
              Request = (HttpWebRequest) WebRequest.Create(Url);

              Request.Method = Method;
          }

          HttpWebResponse Response;
          var ResponseString = "";
          
          try 
          {
              Response = (HttpWebResponse) Request.GetResponse();
              ResponseString = new StreamReader(Response.GetResponseStream()).ReadToEnd();
          } 
          catch (System.Net.WebException ex)
          {
              Response = (HttpWebResponse)ex.Response;
              ResponseString = new StreamReader(Response.GetResponseStream()).ReadToEnd();
          }
          catch (Exception ex)
          {
              Console.WriteLine($"\n*** EXCEPTION ERROR *** {ex}\n");
          }

          Console.WriteLine($"{Method} - {Url}:\n{ResponseString}\n");

          return ResponseString;
      }

      private static Dictionary InitializeDictionary () 
      {
          return new Dictionary();
      }   
  }