Issue
I want to change my account leverage on FTX with rel="nofollow noreferrer">there rest API. Just for a test because after that I want to post an order. But I cant get both of them working and for some reason I cant figure out how to do it.
So far I am able to do a get request and the authentication for it. This is the code I use for such an get request WITH authentication. I use PHP to do it and use Javascript to fetch the php file.
<?php
// API keys.
$keys = array(
'apiKey'=> '....',
'secretKey'=> '....'
);
// Get current time * 1000 to make sure I get a timestamp in milliseconds. Which is needed for the api.
$timestamp = time() * 1000;
// Base url for all api calls.
$baseURL = 'https://ftx.com/api';
// Specified url endpoint. This comes after the baseUrl.
$endPoint = '/account';
// Parameters that are needed for the endPoint its call.
$parameters = '';
// Data that should be added to the encryption of the keys.
$signature = $timestamp . 'GET/api' . $endPoint;
// Hashing the secret key.
$secret = hash_hmac('sha256', $signature, $keys['secretKey']);
// All parts together.
$url = $baseURL . $endPoint . '?' . $parameters;
//Init session for CURL.
$ch = curl_init();
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Make sure curl_exec() will return the result on success and not "success" on success. Also removes error when fetched in Javascript.
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_FAILONERROR, true);
// Init headers for access to the API signed data.
$headers = array();
$headers[] = 'FTX-KEY: ' . $keys['apiKey'];
$headers[] = 'FTX-SIGN: ' . $secret;
$headers[] = 'FTX-TS: ' . $timestamp;
// Setting headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute request.
$result = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
echo($error_msg);
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
echo($result);
exit();
?>
So again, this worked. But now I want to do a POST request. According to the authentication documentation I only need to add a request body to the authentication it says. I think these are the $parameters. But im not sure. Anyway, this is my code so far:
<?php
// API keys.
$keys = array(
'apiKey'=> 'normal',
'secretKey'=> 'secret'
);
// Get current time * 1000 to make sure I get a timestamp in milliseconds. API asks for it this way.
$timestamp = time() * 1000;
// Base url for all api calls.
$baseURL = 'https://ftx.com/api';
// Specified url endpoint. This comes after the baseUrl.
$endPoint = '/account/leverage';
// Parameters that are needed for the endPoint its call.
$parameters = 'leverage=10';
// Data that should be added to the encryption of the keys. NOTE: Added $parameters.
$signature = $timestamp . 'POST/api' . $endPoint . '?' . $parameters;
// Hashing the secret key.
$secret = hash_hmac('sha256', $signature, $keys['secretKey']);
// For account data
$url = $baseURL . $endPoint . '?' . $parameters;
// Init session for CURL.
$ch = curl_init();
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Make sure curl_exec() will return the result on success and not "success" on success. Also removes error when fetched in Javascript.
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_FAILONERROR, true);
// Tried this, but didn't do much.
// curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
// Init headers for access to the API signed data.
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Content-type: application/x-www-form-urlencoded';
$headers[] = 'FTX-KEY: ' . $keys['apiKey'];
$headers[] = 'FTX-SIGN: ' . $secret;
$headers[] = 'FTX-TS: ' . $timestamp;
// Setting headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute request.
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo(curl_error($ch));
exit();
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
echo($result);
?>
This url is an "example" they give for the authentication. At the bottem there is a "POST signature example" with parameters like this.
b'1588591856950POST/api/orders{"market": "BTC-PERP", "side": "buy", "price": 8500, "size": 1, "type": "limit", "reduceOnly": false, "ioc": false, "postOnly": false, "clientId": null}'
The first b'
part I think is something from Python, the long number is the timestamp that I added, the POST/api/orders
I also have. But the object (I think its a object) I do not have. I tried it but didn't succeed.
The error I get from the API is 400 bad request. When I change something with the signature I most of the time get a 401 Unauthorized. For example when changing the timestamp to seconds or removing the '?' in the signature also gives 401.
There can be nothing wrong with the url part, since I did the get request already. So if there is any help, I would appreciate it alot. Before I used Binance, which works perfect. But they are doing some sketchy stuff so I have to move to make sure my money isn't gonna disappear in case they go bad :(
EDIT:
$parameters = 'leverage=10';
gives me a $signature of
1627494427000POST/api/account/leverage?leverage=10
and results in a 400 Bad request. API message: "Missing parameter leverage".
$specialParam = json_encode(['leverage' => '10']);
gives me a signature of
1627494427000POST/api/account/leverage?{"leverage":"10"}
and results in a 400 Bad request.
Doing the same for both but without the . '?' .
part in my $signature results for both into a 401 Unauthenticated... API message: "Not logged in"
Solution
I figured out how to do it. It had to do with the $parameters
and @signature
. When doing a POST request you need to json_encode()
the parameters and then use it in the $signature
. See $specialParam
. Below code makes it possible to chance leverage.
<?php
// API keys.
$keys = array(
'apiKey'=> 'normal',
'secretKey'=> 'secret'
);
// Get current time * 1000 to make sure I get a timestamp in milliseconds. API asks for it this way.
$timestamp = time() * 1000;
// Base url for all api calls.
$baseURL = 'https://ftx.com/api';
// Specified url endpoint. This comes after the baseUrl.
$endPoint = '/account/leverage';
// Encoded parameters, needed for authentication and post request.
$specialParam = json_encode(['leverage' => 10]);
// Data that should be added to the encryption of the keys.
$signature = $timestamp . 'POST/api' . $endPoint . $specialParam;
// Hashing the secret key.
$secret = hash_hmac('sha256', $signature, $keys['secretKey']);
// For account data
$url = $baseURL . $endPoint;
// Init session for CURL.
$ch = curl_init();
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $specialParam);
// Init headers for access to the FTX API signed data.
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Content-Type: application/json';
$headers[] = 'FTX-KEY: ' . $keys['apiKey'];
$headers[] = 'FTX-SIGN: ' . $secret;
$headers[] = 'FTX-TS: ' . $timestamp;
// Setting headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute request.
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo(curl_error($ch));
exit();
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
echo($result);
?>
Be aware that the error catching part is not really a good/trustable way of catching errors. Atleast for me it didn't always worked out as I hoped it would. I was missing some API messages that say more then 400/401.
Here is another example of how to set an order on FTX:
<?php
// API keys.
$keys = array(
'apiKey'=> 'normal',
'secretKey'=> 'secret'
);
// Get current time * 1000 to make sure I get a timestamp in milliseconds. API asks for it this way.
$timestamp = time() * 1000;
// Base url for all api calls.
$baseURL = 'https://ftx.com/api';
// Specified url endpoint. This comes after the baseUrl.
$endPoint = '/orders';
$specialParam = json_encode(
[
'market'=> 'AAVE/USDT',
'side' => 'buy',
'price' => null,
'type' => 'market',
'size' => 3
]
);
// Data that should be added to the encryption of the keys.
$signature = $timestamp . 'POST/api' . $endPoint . $specialParam;
// Hashing the secret key.
$secret = hash_hmac('sha256', $signature, $keys['secretKey']);
// For account data
$url = $baseURL . $endPoint;
// Init session for CURL.
$ch = curl_init();
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $specialParam);
// Init headers for access to the FTX API signed data.
$headers = array();
// $headers[] = 'Content-type: application/x-www-form-urlencoded';
$headers[] = 'Accept: application/json';
$headers[] = 'Content-Type: application/json';
$headers[] = 'FTX-KEY: ' . $keys['apiKey'];
$headers[] = 'FTX-SIGN: ' . $secret;
$headers[] = 'FTX-TS: ' . $timestamp;
// Setting headers
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute request.
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo(curl_error($ch));
exit();
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
echo($result);
?>
If your also interrested in a GET request, I got you covered. This get the last price there is (not of the past, but of the current).:
<?php
// To make sure I always get the last line existing.
$startTime = time() - 900;
// Base url for all api calls.
$baseURL = 'https://ftx.com/api';
// Specified url endpoint. This comes after the baseUrl.
$endPoint = '/markets/ETH/USDT/candles';
// Parameters that are needed for the endPoint its call.
$parameters = 'resolution=900&start_time=' . $startTime;
// All parts together.
$url = $baseURL . $endPoint . '?' . $parameters;
//Init session for CURL.
$ch = curl_init();
// Options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Make sure curl_exec() will return the result on success and not "success" on success. Also removes error when fetched in Javascript.
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_FAILONERROR, true);
// Execute request.
$result = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
echo($error_msg);
}
// Ends the CURL session, frees all resources and deletes the curl (ch).
curl_close($ch);
echo($result);
?>
I hope these are enough examples to make the FTX API usable. Documentation of FTX is unfortunate hard to follow :(
Answered By - Allart Answer Checked By - David Goodson (WPSolving Volunteer)