Issue with CRM imports

Hello,

I’m trying to import CSV files with the /crm/v3/imports endpoint, without any success so far. I’ve read thoroughly the issue here and some others, but still I can’t find a way to make it work. As mentionned by @JakeBreaksStuff I’m surprised by the lack of documentation, and I would also add that a few hints in the HTPP response (“Bad request” really don’t help) would be really helpful (even more than a documentation !).

At first I had 415 errors and now 400, can you confirm me I’m still on the right way ? :slightly_smiling_face:

I’m not sure how to send the files param. nodejs form-data does not accept arrays, so I try without array, or with files[] or files[0] or files with JSON.stringify([file…]) but no solution worked, always get a 400 Bad Request.

Also I have to stringify the importRequest object as form-data does not work with nested object (issue here).

Thus I’m not sure where’s my issue : the files param ? the importRequest param ? something wrong in my column mapping vs CSV ? I’ve checked and dumped formData several times to be sure :confused: Again, giving a hint in the HTTP response data would really help…

So here is my code :

 const dateFormat = 'DD/MM/YYYY';
 const csvFile = fs.readFileSync(hubspotExportFileName);
 const csvFilePath = `${__dirname}/../../${csvFile}`;

 const accessToken = await getHubspotAccessToken();

 const importRequest = {
 name: `import-${moment().format('YYYYMMDD')}`,
 files: [
 {
 fileName: csvFile,
 fileFormat: 'CSV',
 dateFormat,
 fileImportPage: {
 hasHeader: true,
 columnMappings: [
 {
 ignored: false,
 columnName: 'email',
 idColumnType: 'HUBSPOT_ALTERNATE_ID',
 propertyName: 'email',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'firstname',
 idColumnType: null,
 propertyName: 'firstname',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'contact_role',
 idColumnType: null,
 propertyName: 'contact_role',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'zip',
 idColumnType: null,
 propertyName: 'zip',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'subscription_funnel_step',
 idColumnType: null,
 propertyName: 'subscription_funnel_step',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'approval_date',
 idColumnType: null,
 propertyName: 'approval_date',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'delivery_date',
 idColumnType: null,
 propertyName: 'delivery_date',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 {
 ignored: false,
 columnName: 'fleet_manager',
 idColumnType: null,
 propertyName: 'fleet_manager',
 foreignKeyType: null,
 columnObjectType: 'CONTACT',
 associationIdentifierColumn: false,
 },
 ],
 },
 },
 ],
 };

 const form = new FormData();
 form.append('importRequest', JSON.stringify(importRequest));
 form.append('files[0]', fs.createReadStream(csvFilePath));

 const url = `https://api.hubapi.com/crm/v3/imports`
 const config = {
 headers: {
 'content-type': 'multipart/form-data',
 Authorization: `Bearer ${accessToken}`,
 },
 };

 try {
 await axios.post(url, form, config);
 } catch (error) {
 console.dir(error);
 }

and here is what my CSV file look like :

33643iA5B4721BA423976D.png

Any idea how to make this works ?

Thank you !

Olivier

Hello @zrOlivier

Are you still having issues with this import?

Curious to know what the difference is bewteen the ones that worked and the ones that didn’t :thinking:

Hello @dennisedson

I’m back on it (had to pause for an emergency); unfortunately I’m still having issues yes. I found a little mistake in my code (missing encoding param in the first readFileSync, thus csvFile was not correct), but still I get 400 errors. I’ve dumped formData and it looks fine. Can you confirm 400 code is an error in the content of the CSV or columnMapping itself ? Or do I have an issue with the request itself (as I said, I’m not sure the way the files param should be sent).

Do you have any working example with NodeJS ? I’ve read this thread also but it seems outdated (mentionning application/x-www-form-urlencoded instead of multipart/form-data as more recent ones insist on).

Thank you,

Olivier

+ 1

I’ve been trying with the hubspot-api-nodejs package, following this example, and reading the implementation. Hourra :tada:, I managed to have it worked… I also had to remove the full path in the importRequest/files/fileName property and put the file name only (contrary to what’s been mentionned in another post).

So, now I’m sure my importRequest config and CSV file are OK, I’m going to investigate why my request with axios does not work (the hubspot-api-nodejs package uses request, which seems deprecated now).

Found my issues by analysing the request of the hubspot package… The boundary parameter was missing in the content-type. I tried earlier with form.getHeaders() but removed it as somehow I did not get the multipart-form-data, probably I messed up on something. The header should look like this :

'Content-Type: multipart/form-data; boundary=--------------------------815564371250734264447724\r\n'

So here is the correct code :

 const form = new FormData();
 form.append('importRequest', JSON.stringify(importRequest));
 form.append('files', fs.createReadStream(csvFilePath));

 const url = `https://${zrConfig.hubspot.hostname}/crm/v3/imports`;
 const config = {
 headers: {
 Authorization: `Bearer ${accessToken}`,
 ...form.getHeaders(),
 },
 };

 await axios.post(url, form, config);

Note :

  • the files param does not need to be an array…
  • importRequest must be stringified (otherwise form-data triggers an error when you append the readStream).
  • again, importRequest/files/fileName is the file name itself, not the full path (seems obvious but other posts here confused me about the full path…)

Hope that helps others :slightly_smiling_face:

Olivier

Hi @zrOlivier
Thanks for the post but it’s not working in Postman as well as the NodeJS code as below
Could you please suggest whats wrong with this

const fs = require('fs');
let data = new FormData();
data.append('importRequest ', '"{\\"name\\":\\"NovemberMarketingEventLeads\\",\\"importOperations\\":{\\"0-1\\":\\"CREATE\\"},\\"dateFormat\\":\\"DAY_MONTH_YEAR\\",\\"files\\":[{\\"fileName\\":\\"dummy-contacts.xlsx\\",\\"fileFormat\\":\\"SPREADSHEET\\",\\"fileImportPage\\":{\\"hasHeader\\":true,\\"columnMappings\\":[{\\"columnObjectTypeId\\":\\"0-1\\",\\"columnName\\":\\"FirstName\\",\\"propertyName\\":\\"firstname\\"},{\\"columnObjectTypeId\\":\\"0-1\\",\\"columnName\\":\\"LastName\\",\\"propertyName\\":\\"lastname\\"},{\\"columnObjectTypeId\\":\\"0-1\\",\\"columnName\\":\\"Email\\",\\"propertyName\\":\\"email\\",\\"columnType\\":\\"HUBSPOT_ALTERNATE_ID\\"}]}}]}"');
data.append('files', fs.createReadStream(filePath));
let config = {
 method: 'post',
 maxBodyLength: Infinity,
 url: 'https://api.hubspot.com/crm/v3/imports',
 headers: { 
 'Authorization': 'Bearer *********************************', 
 'Content-Type': 'multipart/form-data',
 'boundary': '--------------------------815564371250734264447724'
 },
 data : data
};

axios.request(config)

Thanks

Hey @zrOlivier , sorry I didn’t get back to you yesterday. Was out for Election day. Glad you figured it out and thank you for posting here!