I needed to upload a file to Hubspot via API, and associate it to a ticket (via note engagement). The file upload part was a lot of trouble to figure out and no current, complete source appears to exist on the internet. Just putting this out there to avoid the next person some frustration.
Some complicating factors:
1. the hubspot client does not have an upload method. have to use curl, fetch, axios, etc.
2. I had to submit file in multipart format, using form-data package (NOT the native FormData, use the npm package form-data)
3. submitted with node-fetch (NOT the native fetch). I’m using commonjs so specifically version node-fetch@2
4. add a filename to the ‘file’ formdata
5. don’t set the request headers manually, let form-data do it with `formData.getHeaders()`
Some errors along the way were self-explanatory, like your app needs `files` scope, but the above were all discovered by slogging through sparse documentation and by guessing and testing.
More or less how to run:
`npm i –save node-fetch@2 dotenv form-data`
`echo ‘HUBSPOT_API_KEY=”{key_goes_here}”‘ >> .env`
`node hs_upload.js`
hs_upload.js to upload a sample pizza.png image:
const fs = require(“fs”);
const path = require(“path”);
const FormData = require(“form-data”);
const fetch = require(“node-fetch”);
const dotenv = require(“dotenv”);
dotenv.config();
const uploadFileToHubspot = async (filePath, token, api, folderPath) => {
try {
const buffer = fs.readFileSync(filePath);
const fileName = path.basename(filePath);
const formData = new FormData();
formData.append(“file”, buffer, fileName);
formData.append(“fileName”, fileName);
formData.append(“folderPath”, folderPath);
formData.append(
“options”,
JSON.stringify({
access: “PRIVATE”,
overwrite: false,
duplicateValidationStrategy: “NONE”,
duplicateValidationScope: “ENTIRE_PORTAL”,
}),
);
const response = await fetch(api, {
method: “POST”,
headers: {
Authorization: `Bearer ${token}`,
…formData.getHeaders(),
},
body: formData,
});
const contentType = response.headers.get(“content-type”);
let data;
if (contentType && contentType.includes(“application/json”)) {
data = await response.json();
console.log(“Response data:”, data);
} else {
data = await response.text();
console.error(“Unexpected response format:”, data);
return null;
}
} catch (error) {
console.error(“Failed to upload file to Hubspot API:”, error);
return null;
}
};
// Example usage
const filePath = “./pizza.png”;
const token = process.env.HUBSPOT_API_KEY;
const api = “https://api.hubapi.com/files/v3/files”;
const folderPath = “/uploads”;
uploadFileToHubspot(filePath, token, api, folderPath);
Use the response ID from the upload to create whatever engagement you need to associate it with a contact, ticket, etc. That’s documented well.