Authenticated Endpoints
Authentication
All examples assume the following:
- You are using the provided example request object
- You use your API key and secret
- BTCUSD is the default symbol
const request = require('request')
const crypto = require('crypto')
const apiKey = '<Your API key here>'
const apiSecret = '<Your API secret here>'
const baseUrl = 'https://api.bitfinex.com'
const url = '/v1/account_infos'
const nonce = Date.now().toString()
const completeURL = baseUrl + url
const body = {
request: url,
nonce
}
const payload = new Buffer(JSON.stringify(body))
.toString('base64')
const signature = crypto
.createHmac('sha384', apiSecret)
.update(payload)
.digest('hex')
const options = {
url: completeURL,
headers: {
'X-BFX-APIKEY': apiKey,
'X-BFX-PAYLOAD': payload,
'X-BFX-SIGNATURE': signature
},
body: JSON.stringify(body)
}
request.post(
options,
function(error, response, body) {
console.log('response:', body)
}
)
payload := map[string]interface{}{
"request": "/v1/account_infos",
"nonce": fmt.Sprintf("%v", time.Now().Unix()*10000),
}
import "github.com/bitfinexcom/bitfinex-api-go"
client := bitfinex.NewClient().Auth(API_KEY, API_SECRET)
// Full example of authenticated request
package main
import (
"crypto/hmac"
"crypto/sha512"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
API_KEY := "..."
API_SECRET := "..."
url := "https://api.bitfinex.com/v1/"
req, err := http.NewRequest("POST", url+"/account_infos", nil)
if err != nil {
log.Fatal(err)
}
payload := map[string]interface{}{
"request": "/v1/account_infos",
"nonce": fmt.Sprintf("%v", time.Now().Unix()*10000),
}
payload_json, _ := json.Marshal(payload)
payload_enc := base64.StdEncoding.EncodeToString(payload_json)
sig := hmac.New(sha512.New384, []byte(API_SECRET))
sig.Write([]byte(payload_enc))
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
req.Header.Add("X-BFX-APIKEY", API_KEY)
req.Header.Add("X-BFX-PAYLOAD", payload_enc)
req.Header.Add("X-BFX-SIGNATURE", hex.EncodeToString(sig.Sum(nil)))
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
# add in your Gemfile
gem 'bitfinex-rb'
Bitfinex::Client.configure do |conf|
conf.secret = ENV["BFX_API_SECRET"]
conf.api_key = ENV["BFX_API_KEY"]
end
client = Bitfinex::Client.new
package eg.android.example;
import android.util.Base64;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class Examples {
private static final String TAG = Examples.class.getSimpleName();
private static final String ALGORITHM_HMACSHA384 = "HmacSHA384";
private String apiKey = "";
private String apiKeySecret = "";
private long nonce = System.currentTimeMillis();
/**
* public access only
*/
public Examples() {
apiKey = null;
apiKeySecret = null;
}
/**
* public and authenticated access
*
* @param apiKey
* @param apiKeySecret
*/
public Examples(String apiKey, String apiKeySecret) {
this.apiKey = apiKey;
this.apiKeySecret = apiKeySecret;
}
/**
* Creates an authenticated request WITHOUT request parameters. Send a request for Balances.
*
* @return Response string if request successfull
* @throws IOException
*/
public String sendRequestV1Balances() throws IOException {
String sResponse;
HttpURLConnection conn = null;
String urlPath = "/v1/balances";
// String method = "GET";
String method = "POST";
try {
URL url = new URL("https://api.bitfinex.com" + urlPath);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
if (isAccessPublicOnly()) {
String msg = "Authenticated access not possible, because key and secret was not initialized: use right constructor.";
Log.e(TAG, msg);
return msg;
}
conn.setDoOutput(true);
conn.setDoInput(true);
JSONObject jo = new JSONObject();
jo.put("request", urlPath);
jo.put("nonce", Long.toString(getNonce()));
// API v1
String payload = jo.toString();
// this is usage for Base64 Implementation in Android. For pure java you can use java.util.Base64.Encoder
// Base64.NO_WRAP: Base64-string have to be as one line string
String payload_base64 = Base64.encodeToString(payload.getBytes(), Base64.NO_WRAP);
String payload_sha384hmac = hmacDigest(payload_base64, apiKeySecret, ALGORITHM_HMACSHA384);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.addRequestProperty("X-BFX-APIKEY", apiKey);
conn.addRequestProperty("X-BFX-PAYLOAD", payload_base64);
conn.addRequestProperty("X-BFX-SIGNATURE", payload_sha384hmac);
// read the response
InputStream in = new BufferedInputStream(conn.getInputStream());
return convertStreamToString(in);
} catch (MalformedURLException e) {
throw new IOException(e.getClass().getName(), e);
} catch (ProtocolException e) {
throw new IOException(e.getClass().getName(), e);
} catch (IOException e) {
String errMsg = e.getLocalizedMessage();
if (conn != null) {
try {
sResponse = convertStreamToString(conn.getErrorStream());
errMsg += " -> " + sResponse;
Log.e(TAG, errMsg, e);
return sResponse;
} catch (IOException e1) {
errMsg += " Error on reading error-stream. -> " + e1.getLocalizedMessage();
Log.e(TAG, errMsg, e);
throw new IOException(e.getClass().getName(), e1);
}
} else {
throw new IOException(e.getClass().getName(), e);
}
} catch (JSONException e) {
String msg = "Error on setting up the connection to server";
throw new IOException(msg, e);
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
private String convertStreamToString(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line).append('\n');
}
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public long getNonce() {
return ++nonce;
}
public boolean isAccessPublicOnly() {
return apiKey == null;
}
public static String hmacDigest(String msg, String keyString, String algo) {
String digest = null;
try {
SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), algo);
Mac mac = Mac.getInstance(algo);
mac.init(key);
byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
StringBuffer hash = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
hash.append('0');
}
hash.append(hex);
}
digest = hash.toString();
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Exception: " + e.getMessage());
} catch (InvalidKeyException e) {
Log.e(TAG, "Exception: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
return digest;
}
}
Authentication is done using an API key and a secret. To generate this pair, go to the API Access page.
As an example of how to authenticate, we can look at the "account_infos" endpoint.
Take the example payload above.
Nonce
The nonce provided must be strictly increasing.
The authentication procedure is as follows:
- The payload is the parameters object, first JSON encoded, and then encoded into Base64
payload = parameters-object -> JSON encode -> base64
- The signature is the hex digest of an HMAC-SHA384 hash where the message is your payload, and the secret key is your API secret.
signature = HMAC-SHA384(payload, api-secret).digest('hex')
send (api-key, payload, signature)
These are encoded as HTTP headers named:
- X-BFX-APIKEY
- X-BFX-PAYLOAD
- X-BFX-SIGNATURE
All Authenticated Endpoints use POST requests
- POST Account Info
- POST Summary
- POST Deposit
- POST Wallet Balances
- POST Margin Information
- POST Transfer Between Wallets
- POST Withdrawal
- POST Key Permissions
Orders
- POST New Order
- POST Multiple New Orders
- POST Cancel Order
- POST Cancel Multiple Orders
- POST Cancel All Orders
- POST Replace Order
- POST Order Status
- POST Active Orders
- POST Basket Manage
Positions
- POST Active Positions
- POST Claim Position
Historical Data
- POST Balance History
- POST Deposit-Withdrawal History
- POST Past Trades
Margin Funding
- POST New Offer
- POST Cancel Offer
- POST Offer Status
- POST Active Credits
- POST Offers
- POST Active Funding Used in a margin position \
- POST Active Funding Not Used in a margin position
- POST Total Taken Funds
- POST Close Margin Funding
Updated over 2 years ago