title: How to do a PHP POST request for FTX rest API
body: <p>I want to change my <a href="https://docs.ftx.com/?csharp#change-account-leverage" rel="nofollow noreferrer">account leverage</a> on FTX with <a href="https://docs.ftx.com/?csharp#rest-api" rel="nofollow noreferrer">there rest API</a>. 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.</p>
  <p>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.</p>
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  
  // API keys.
  $keys = array(
      'apiKey'=&gt; '....',
      'secretKey'=&gt; '....'
  );
  
  // 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 &quot;success&quot; 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();
  
  ?&gt;
  </code></pre>
  <p>So again, this worked. But now I want to do a POST request. According to the <a href="https://docs.ftx.com/?csharp#authentication" rel="nofollow noreferrer">authentication documentation</a> 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:</p>
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  
  // API keys.
  $keys = array(
      'apiKey'=&gt; 'normal',
      'secretKey'=&gt; '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 &quot;success&quot; 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);
  
  ?&gt;
  </code></pre>
  <p><a href="https://blog.ftx.com/blog/api-authentication/" rel="nofollow noreferrer">This url</a> is an &quot;example&quot; they give for the authentication. At the bottem there is a &quot;POST signature example&quot; with parameters like this.</p>
  <pre><code>b'1588591856950POST/api/orders{&quot;market&quot;: &quot;BTC-PERP&quot;, &quot;side&quot;: &quot;buy&quot;, &quot;price&quot;: 8500, &quot;size&quot;: 1, &quot;type&quot;: &quot;limit&quot;, &quot;reduceOnly&quot;: false, &quot;ioc&quot;: false, &quot;postOnly&quot;: false, &quot;clientId&quot;: null}'
  </code></pre>
  <p>The first <code>b'</code> part I think is something from Python, the long number is the timestamp that I added, the <code>POST/api/orders</code> I also have. But the object (I think its a object) I do not have. I tried it but didn't succeed.</p>
  <p>The <strong>error</strong> 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.</p>
  <p>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 :(</p>
  <h2><strong>EDIT:</strong></h2>
  <p><code>$parameters = 'leverage=10';</code> gives me a $signature of</p>
  <pre><code>1627494427000POST/api/account/leverage?leverage=10
  </code></pre>
  <p>and results in a 400 Bad request. API message: &quot;Missing parameter leverage&quot;.</p>
  <p><code>$specialParam = json_encode(['leverage' =&gt; '10']);</code> gives me a signature of</p>
  <pre><code>1627494427000POST/api/account/leverage?{&quot;leverage&quot;:&quot;10&quot;}
  </code></pre>
  <p>and results in a 400 Bad request.</p>
  <p>Doing the same for both but without the <code>. '?' .</code> part in my $signature results for both into a 401 Unauthenticated... API message: &quot;Not logged in&quot;</p>