How to invoke Binance API with PHP

Introduction

Binance is one of the biggest cryptocurrency market today (5th March 2022). It provides tons of API to trigger trades (bot trading), and also to aggregate trade data.

I am involved in a project where we are collecting the details of all trades for multiple users for taxing and accounting purpose.

In this guide, I will show you how we are invoking the Binance API with for users with user API Keys.

Pre-requisites

To invoke APIs which are specific to users, the user API Key is required. For Binance, this is a combination of Public API Key and Private API Key. All Binance APIs returns a JSON Object or an Array.

Invoke Binance API Function Signature

Lets start by defining the function signature as:

private function invokeBinanceAPI($path, $data = [], $public, $private)
$path is the API endpoint. $data will contain the input for the API calls. $public and $private is the user public and private keys.

Construct the Endpoint Base URL

$url = 'https://api.binance.com'.$path;

Example:

//https://api.binance.com/api/v3/account 

Construct the Query Part of the URL

$timestamp = time()*1000;
$query = '';
$params = array();
$data['timestamp'] = $timestamp;
foreach($data as $key => $field){
	array_push($params, $key.'='.$field);
}
$query = implode('&', $params);

This will construct the query string with the mandatory parameter `timestamp` and other API specific parameters.

An example of query parameter for account info API is:

recvWindow=60000&timestamp=1646760577000&signature=0268040707c83284g768223dcc6b465226a513bad5585ae5906dd42335f9379d

Construct sha256 Signature of Query Parameter With Private Key

To invoke the Binance API, a signature has to be passed which is basically SHA265 has of the query parameter with the private key as the hash key.

$signature = hash_hmac('sha256', $query, $private);

Set Public API Key In Header

Now set the Public Key in HTTP Header as:

$opts = [
	"http" => [
		"method" => "GET",
		"header" => "X-MBX-APIKEY: $public\r\n",
		"ignore_errors" => true
	]
];
$this->context = stream_context_create($opts);

In order to construct the final URL to be invoked, append the query string and signature parameter.

$endpoint = $url . '?' .$query . '&signature='. $signature;

For example, the final URL for retrieving the Account Info of a user will be similar to:

https://api.binance.com/api/v3/account?recvWindow=60000&timestamp=1646760577000&signature=878092442c83284d89245dcc6b465226a513bad5585ae5906dd24925a3249j
	

Full Function to Invoke the Binance API

private function invokeBinanceAPI($path, $data = [], $public, $private){
        $url = 'https://api.binance.com'.$path;
        $timestamp = time()*1000;
        $query = '';
        $params = array();
        $data['timestamp'] = $timestamp;
        foreach($data as $key => $field){
            array_push($params, $key.'='.$field);
        }
        $query = implode('&', $params);
        $signature = hash_hmac('sha256', $query, $private);
        $opts = [
            "http" => [
                "method" => "GET",
                "header" => "X-MBX-APIKEY: $public\r\n",
                'ignore_errors' => true
            ]
        ];
        $this->context = stream_context_create($opts);
        $endpoint = $url . '?' .$query . '&signature='. $signature;
        set_error_handler(function ($err_severity, $err_msg, $err_file, $err_line, array $err_context)
        {
            throw new Exception( $err_msg, $err_severity );
        }, E_WARNING);
        try {
            $request = @file_get_contents($endpoint, false, $this->context);
        }
        catch (Exception $e) {
            return null;
        }
        restore_error_handler();        
        return json_decode($request);
    }
Note that an error handler has been added so that end point errors like php_network_getaddresses, SSL: Handshake timed out can be caught.

Function Invocation Examples

$path = '/api/v3/account';
$data = $this->invokeBinanceAPI($path, ['recvWindow' => 60000], $publicKey, $privateKey);

Sample Response of Get Account Info Binance API

{
    "makerCommission":10,
    "takerCommission":10,
    "buyerCommission":0,
    "sellerCommission":0,
    "canTrade":true,
    "canWithdraw":true,
    "canDeposit":true,
    "updateTime":1646728783994,
    "accountType":"SPOT",
    "balances":[
        {"asset":"BTC","free":"0.00000000","locked":"0.00000000"},
        {"asset":"LTC","free":"0.00000000","locked":"0.00000000"},
        {"asset":"ETH","free":"0.00000000","locked":"0.00000000"},
        {"asset":"NEO","free":"0.00000000","locked":"0.00000000"},
        {"asset":"BNB","free":"0.08218490","locked":"0.00000000"},
        {"asset":"QTUM","free":"0.00000000","locked":"0.00000000"},
        {"asset":"EOS","free":"0.00000000","locked":"0.00000000"},
        {"asset":"SNT","free":"0.00000000","locked":"0.00000000"},
        {"asset":"BNT","free":"0.00000000","locked":"0.00000000"},
        {"asset":"GAS","free":"0.00000000","locked":"0.00000000"},
        {"asset":"BCC","free":"0.00000000","locked":"0.00000000"},
        .....
        .....
        {"asset":"ICN","free":"0.00000000","locked":"0.00000000"},
        {"asset":"API3","free":"0.00000000","locked":"0.00000000"},
        {"asset":"XNO","free":"0.00000000","locked":"0.00000000"},
        {"asset":"WOO","free":"0.00000000","locked":"0.00000000"},
        {"asset":"ALPINE","free":"0.00000000","locked":"0.00000000"},
        {"asset":"T","free":"0.00000000","locked":"0.00000000"}
    ],
    "permissions":["SPOT"]
}  
    
Asha

Asha

I am a self mentored web enthusiast who likes to inspect element everything I see on the web.