API Reference

Getting Started

Sandbox Environment

Restful URL: [https://api-glb.sim.hashkeydev.com]

WebSocket: [wss://stream-glb.sim.hashkeydev.com]

Production Environment

Restful URL: [https://api-glb.hashkey.com]

WebSocket: [wss://stream-glb.hashkey.com]

Python [POST] Order Submit sample

👍

For Production account please change base_url to https://api-glb.hashkey.com

import time
import requests
import hashlib
import hmac
import json

"""
####################################################################################################################################
# Test REST API
#
# Copyright: Hashkey Trading 2024 All rights reserved.
# Please note the API code is provided "As Is" basis, without warranty of any kind, either express or implied, including
# without limitation, warranties that the API code is free of defects, merchantable, non-infringing or fit for a particular purpose
####################################################################################################################################
"""

class RestAPIClient:
    def __init__(self, base_url, user_key, user_secret):
        """
        Initialize the RestAPIClient with base URL, user key, and user secret.

        Args:
            base_url (str): The base URL of the API.
            user_key (str): The user key for authentication.
            user_secret (str): The user secret for authentication.
        """
        self.base_url = base_url
        self.user_key = user_key
        self.user_secret = user_secret
        self.headers = {
            'X-HK-APIKEY': user_key,
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        }

    def get_timestamp(self):
        """
        Get the current timestamp in milliseconds.

        Returns:
            int: The current timestamp.
        """
        return int(time.time() * 1000)

    def create_signature(self, content):
        """
        Create HMAC signature for authentication.

        Args:
            content (str): The content to be signed.

        Returns:
            str: The HMAC signature.
        """
        content_bytes = content.encode('utf-8')
        hmac_digest = hmac.new(
            self.user_secret.encode('utf-8'),
            content_bytes,
            hashlib.sha256
        ).hexdigest()
        return hmac_digest

    def place_order(self, symbol, side, order_type, quantity, price=None):
        """
        Place an order.

        Args:
            symbol (str): The trading pair symbol (e.g., ETHUSD).
            side (str): The order side (BUY or SELL).
            order_type (str): The order type (LIMIT or MARKET).
            quantity (str): The order quantity.
            price (str, optional): The order price (required for LIMIT orders).

        Returns:
            dict or None: The JSON response if successful, None otherwise.
        """
        timestamp = self.get_timestamp()
        data = {
            "symbol": symbol,
            "side": side,
            "type": order_type,
            "price": price,
            "quantity": quantity,
            "timestamp": timestamp
        }
        if order_type == 'MARKET':
            del data['price']

        data_string = '&'.join([f"{key}={value}" for key, value in data.items()])
        signature = self.create_signature(data_string)
        data['signature'] = signature

        response = requests.post(
            f"{self.base_url}/api/v1/spot/order",
            headers=self.headers,
            data=data
        )
        
        if response.status_code == 200:
            response_json = response.json()
            print("Response:")
            print(json.dumps(response_json, indent=4))  # Print formatted JSON response
            return response_json
        else:
            try:
                error_json = response.json()
                print("Error:")
                print(json.dumps(error_json, indent=4))  # Print formatted error response
            except json.JSONDecodeError:
                print(f"Error: {response.status_code} - {response.text}")
            return None

if __name__ == '__main__':
    # Example usage:
    # Create an instance of RestAPIClient with your API credentials
    # For Production account please change base_url to  https://api-glb.hashkey.com
    api_client = RestAPIClient(
        base_url="https://api-glb.sim.hashkeydev.com",
        user_key="your_user_key",
        user_secret="your_user_secret"
    )
    # Place an order with the desired parameters
    api_client.place_order("ETHUSDT", "BUY", "LIMIT", "0.01", "3000")

Python [GET] Account balance sample

👍

For Production account please change base_url to https://api-glb.hashkey.com

import time
import requests
import hashlib
import hmac
import json

"""
####################################################################################################################################
# Test REST API
#
# Copyright: Hashkey Trading 2024 All rights reserved.
# Please note the API code is provided "As Is" basis, without warranty of any kind, either express or implied, including
# without limitation, warranties that the API code is free of defects, merchantable, non-infringing or fit for a particular purpose
####################################################################################################################################
"""

class RestAPIClient:
    def __init__(self, base_url, user_key, user_secret):
        """
        Initialize the RestAPIClient with base URL, user key, and user secret.

        Args:
            base_url (str): The base URL of the API.
            user_key (str): The user key for authentication.
            user_secret (str): The user secret for authentication.
        """
        self.base_url = base_url
        self.user_key = user_key
        self.user_secret = user_secret
        self.headers = {
            'X-HK-APIKEY': user_key,
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        }

    def get_timestamp(self):
        """
        Get the current timestamp in milliseconds.

        Returns:
            int: The current timestamp.
        """
        return int(time.time() * 1000)

    def create_signature(self, content):
        """
        Create HMAC signature for authentication.

        Args:
            content (str): The content to be signed.

        Returns:
            str: The HMAC signature.
        """
        content_bytes = content.encode('utf-8')
        hmac_digest = hmac.new(
            self.user_secret.encode('utf-8'),
            content_bytes,
            hashlib.sha256
        ).hexdigest()
        return hmac_digest

    def get_account_info(self):
        """
        Get account information.

        Returns:
            dict or None: The JSON response if successful, None otherwise.
        """
        timestamp = self.get_timestamp()
        data = {
            "timestamp": timestamp
        }
        query_string = '&'.join([f"{key}={value}" for key, value in data.items()])
        signature = self.create_signature(query_string)
        
        response = requests.get(
            f"{self.base_url}/api/v1/account?{query_string}&signature={signature}",
            headers=self.headers
        )
        
        if response.status_code == 200:
            response_json = response.json()
            print("Response:")
            print(json.dumps(response_json, indent=4))  # Print formatted JSON response
            return response_json
        else:
            try:
                error_json = response.json()
                print("Error:")
                print(json.dumps(error_json, indent=4))  # Print formatted error response
            except json.JSONDecodeError:
                print(f"Error: {response.status_code} - {response.text}")
            return None

if __name__ == '__main__':
    # Example usage:
    # Create an instance of RestAPIClient with your API credentials
    # For Production account please change base_url to  https://api-glb.hashkey.com
    api_client = RestAPIClient(
        base_url="https://api-glb.sim.hashkeydev.com",
        user_key="your_user_key",
        user_secret="your_user_secret"
    )
    # Get account information
    api_client.get_account_info()

General API Information


  • All responses will return a JSON object or array.

  • Data is returned in ascending order with the earlier data displayed first and subsequent updates appearing later

  • All time or timestamp-related variables are measured in milliseconds (ms)

  • HTTP 4XX error code indicate that the request content is invalid. This typically originates from the client's end.

  • HTTP 429 error code indicates that the request rate limit has been exceeded.

  • HTTP 418 error code when our server have detected the IP address continues to send subsequent requests after receiving 429 error code and is automatically blocked

  • HTTP 5XX indicates an internal system error. This signifies that the issue originates within the trading system. When addressing this error, it's important not to immediately categorise it as a failed task. The execution status is uncertain, it could potentially be either successful or unsuccessful.

  • For GET endpoints, parameters must be sent as query strings.

  • For POST, PUT, and DELETE endpoints, parameters must be sent as query strings or in the request body with the content type set to application/x-www-form-urlencoded.

  • Request Parameters can be sent in any order.

  • If there are parameters in both query string and request body, only the parameters of query string will be used.

Access Restrictions


  • If any rate limit is violated, a 429 error code will be returned

  • Each API endpoint has an associated with a specific weight, and certain endpoints may possess varying weights based on different parameters. Endpoints that consume more resources will have a higher weight assigned to them.

  • Upon receiving 429 error code, please take precautionary steps to cease sending requests. API abuse is strictly prohibited

  • It is recommended to use Websocket API to obtain corresponding real-time data as much as possible to reduce the traffic of access restrictions caused by frequent API requests.

Order Rate Limiting


  • Unless explicitly stated otherwise, each API Key has a default rate limit of 2 requests per second for query-related endpoints, while order-related endpoints allow 10 requests per second.

  • When the number of orders exceeds the set limit, a response with an HTTP CODE 429 will be received. Please wait 1 minute for the suspended period to expire.

Endpoint Security Types


  • Each endpoint is assigned a security type that determines how you interact with it.

  • The API-KEY must be passed in the REST API header as X-HK-APIKEY.

  • API-KEY and SECRET-KEY are case-sensitive.

  • By default, API-KEY have access to all secure endpoints.

API-KEY Management


  • Users have to log in the exchange website and apply for an API-KEY, please make sure to remember the following information when creating an API key:

    • Access key: API access key
    • Secret key: The key used for signature authentication encryption (visible to the application only)
  • Users have to assign permissions to API-KEY. There are two kinds of permissions,

    • READ read permission is used for data query interfaces such as order query, transaction query, etc.
    • TRADE read-write permission is used for order placing, order cancelling, including transfer permission whereby user can transfer between subaccounts under the same main trading account
  • Both private REST and WebSocket modes require users to authenticate the transaction through the API-KEY passed in the API header. Refer to the following Authentication chapter for the signature algorithm of the API-KEY.