CMS Files API on PHP - Upload a new file - Error 400 Bad Request

Hi, I’m currently integrating CMS Files API to my project to be able to upload files from my project to the HubSpot File Manager. I followed and used the sample PHP script on https://legacydocs.hubspot.com/docs/methods/files/v3/upload_new_file but I kept getting Error 400 - Bad Request response from the server. I’m using Oauth2.0 for authentication.

function upload_file($file_attachment = null) {
 if (!$file_attachment || !$this->access_token) return;

 $this->url = 'http://api.hubapi.com/filemanager/api/v3/files/upload';
 $this->headers[] = 'content-type: multipart/form-data';
 $this->headers[] = sprintf('Authorization: Bearer %s', $this->access_token);

 $upload_file = new CURLFile($file_attachment['file_attachment']['tmp_name'], $file_attachment['file_attachment']['type'], $file_attachment['file_attachment']['name']);

 $file_options = array(
 "access" => "PUBLIC_INDEXABLE",
 "ttl" => "P3M",
 "overwrite" => false,
 "duplicateValidationStrategy" => "NONE",
 "duplicateValidationScope" => "ENTIRE_PORTAL"
 );

 $post_data = array(
 "file" => $upload_file,
 "fileName" => $file_attachment->title,
 "options" => json_encode($file_options),
 "folderPath" => "/docs",
 );

 $process = $this->process($post_data, 'POST', TRUE);

 return $process;
 }

function process($data = null, $action = 'POST', $return_response = FALSE) {
 $ch = curl_init();

 curl_setopt($ch, CURLOPT_URL, $this->url);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

 if ($action !== 'GET') {
 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
 curl_setopt($ch, CURLOPT_POST, 1);
 }

 if($action == 'DELETE') curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");

 if (count($this->headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);

 $result = curl_exec($ch);
 $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
 if (curl_errno($ch)) {
 echo 'Error:' . curl_error($ch);
 }
 curl_close($ch);

 if ($return_response) return $result;

 if ($http_code == 200) return TRUE;
 return;
 }

I also checked other posts like https://community.hubspot.com/t5/APIs-Integrations/Not-able-to-upload-file-through-file-API/td-p/301404 - which uses the old v2 file upload endpoint, tried applying it to my code, but still returning the same error.

I tested other endpoints like Delete a File, Create a Folder and it works properly. Upload a file is the only endpoint that returns Error 400. Any help would be appreciated.

Hello @melumbs ,

Sorry that you are having these issues. I just ran the example code from the docs and successfully uploaded a file.

Wondering if @quentin_lamamy has any thoughts on this one!

I will check this post in 20 min I’m on the road to go back home :slightly_smiling_face:

Hi @dennisedson, can you confirm if you run the code on an HTTPS environment? Because I’ve been testing the same PHP code from the example on localhost and kept getting error 400.

Hi @melumbs,

Can you provide us the request and the answer in the call-log of your api key ? You can get it in settings > integrations > apikey. It will help us to understand what is going wrong.

Hi @quentin_lamamy ,

I have checked the call logs from the two HubSpot accounts that I’m using for the development of the integration. Unfortunately, there are no API logs under the file upload endpoint. Not sure if it’s because I’m using Oauth2.0 for the authentication.

ok, i see that your code is an extract of a class, can you post the whol class code and the code which is using this class to upload a file ?

Hi @quentin_lamamy,

Thanks but I think I finally got it working now. I used the code below as a reference and convert it into a PHP class.

$apikey = '[Your HubSpot API Key]';
$url = "http://api.hubapi.com/filemanager/api/v3/files/upload?hapikey=" . $apikey;
$realpath = getcwd()."\\example_file.txt";

// cURL headers
$headers = array("Content-Type:multipart/form-data"); 

$upload_file = new CURLFile($realpath,'application/octet-stream', 'example_file.txt');

$file_options = array(
 "access" => "PUBLIC_INDEXABLE",
 "ttl" => "P3M",
 "overwrite" => false,
 "duplicateValidationStrategy" => "NONE",
 "duplicateValidationScope" => "ENTIRE_PORTAL"
);

$post_data = array(
 "file" => $upload_file,
 "options" => json_encode($file_options),
 "folderPath" => "/", // /docs
);

$ch = curl_init(); 

$options = array( 
 CURLOPT_URL => $url, 
 CURLOPT_HEADER => true, 
 CURLOPT_POST => 1, 
 CURLOPT_HTTPHEADER => $headers, 
 CURLOPT_POSTFIELDS => $post_data, 
 CURLOPT_RETURNTRANSFER => true,
); 

// cURL options 
curl_setopt_array($ch, $options); 
$result = curl_exec($ch); 

print_r($result);

if(!curl_errno($ch)) { 
 $info = curl_getinfo($ch); 
 if ($info['http_code'] == 200) {
 $msg = "File uploaded successfully";
 echo $msg; 
 }
} else { 
 $errmsg = curl_error($ch); 
 echo $errmsg; 
} 

curl_close($ch);

The code above also works well when using OAuth 2.0 for authentication.

It’s weird because it doesn’t work (for me at least) when I use

curl_setopt()

for setting the curl options.

Using

curl_setopt_array()

for setting up the curl options did the trick for me.

Good news if you succeed to do what you want. If your issue is solved don’t forget to flag your issue as solved.

Reposting the Solution:

Got it working using the code below - converted it to a PHP class afterwards:

$apikey = '[Your HubSpot API Key]';
$url = "http://api.hubapi.com/filemanager/api/v3/files/upload?hapikey=" . $apikey;
$realpath = getcwd()."\\example_file.txt";

// cURL headers
$headers = array("Content-Type:multipart/form-data"); 

$upload_file = new CURLFile($realpath,'application/octet-stream', 'example_file.txt');

$file_options = array(
 "access" => "PUBLIC_INDEXABLE",
 // "ttl" => "P3M",
 "overwrite" => false,
 "duplicateValidationStrategy" => "NONE",
 "duplicateValidationScope" => "ENTIRE_PORTAL"
);

$post_data = array(
 "file" => $upload_file,
 "options" => json_encode($file_options),
 "folderPath" => "/",
);

$ch = curl_init(); 

$options = array( 
 CURLOPT_URL => $url, 
 CURLOPT_HEADER => true, 
 CURLOPT_POST => 1, 
 CURLOPT_HTTPHEADER => $headers, 
 CURLOPT_POSTFIELDS => $post_data, 
 CURLOPT_RETURNTRANSFER => true,
); 

// cURL options 
curl_setopt_array($ch, $options); 
$result = curl_exec($ch); 
echo $result; 

if(!curl_errno($ch)) { 
 $info = curl_getinfo($ch); 
 if ($info['http_code'] == 200) {
 $msg = "File uploaded successfully";
 echo $msg; 
 }
} else { 
 $errmsg = curl_error($ch); 
 echo $errmsg; 
} 

curl_close($ch);

curl_setopt()

is not working for me, used

curl_setopt_array()

to get it work.