Programatic file upload to deal does not work (different results with sdk and direct upload, nodejs)

Hello,

we try to upload a file to a deal which is working with insomnia but does not work with our nextjs application nor a dedicated nodejs test application. Using the latest node lts we create two test applications. One where we use the generated code from insomnia

const http = require("http");

const hostname = "127.0.0.1";
const port = 3005;

const server = http.createServer((req, res) => {
  const fs = require("fs");
  const FormData = require("form-data");
  const fetch = require("node-fetch");
  const formData = new FormData();

  formData.append("file", fs.createReadStream("./large_image.jpg"));
  formData.append("deal_id", "8834");

  let url =
    "https://api.pipedrive.com/v1/files?api_token=<API_TOKEN>";

  let options = {
    method: "POST",
    headers: {
      "Content-Type": "multipart/form-data",
    },
  };

  options.body = formData;

  fetch(url, options)
    .then((res) => res.json())
    .then((json) => console.log(json))
    .catch((err) => console.error("error:" + err));

  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("check logs for upload info\n");
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

This example always responses with

{
  success: false,
  error: 'No files were provided with the request.',
  error_info: 'Please check developers.pipedrive.com for more information about Pipedrive API.',
  data: null,
  additional_data: null
}

We don’t use the pipedrive sdk as we utilize the nextjs fetch cache mechanics and therefore call the APIs our self, which worked fine till we needed the file upload.

We then created another test application utilizing the pipedrive sdk.

const http = require("http");

const hostname = "127.0.0.1";
const port = 3005;

const server = http.createServer((req, res) => {
  //All tutorial Node.Js code examples are for reference only and shouldn't be used in production code as is. In production, a new new pipedrive.ApiClient() instance should be initialised separately for each request.
  const pipedrive = require("pipedrive");
  const defaultClient = new pipedrive.ApiClient();

  // Configure authorization by settings api key
  // PIPEDRIVE_API_KEY is an environment variable that holds real api key
  defaultClient.authentications.api_key.apiKey =
    "<API_KEY>";

  async function addFile() {
    try {
      console.log("Sending request...");

      const api = new pipedrive.FilesApi(defaultClient);

      const filepath = "./large_image.jpg"; // the filepath for the file you want to attach

      // you can assign a file to a deal, person, organization, activity or product by including the appropriate resource id
      const response = await api.addFile(filepath, {
        deal_id: 8834,
        // person_id: 1,
        // org_id: 1,
        // activity_id: 1,
        // product_id: 1
      });

      console.log("File was added successfully!", response);
    } catch (err) {
      const errorToLog = err.context?.body || err;

      console.log("Adding a file failed", errorToLog);
    }
  }

  addFile();

  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("check logs for upload info\n");
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

The interesting part here is, that based on the response the upload was successful but the file has not been assigned to the deal, so for our agents the file is not visible.

File was added successfully! AddFile {
  success: true,
  data: FileData {
    id: 3077,
    user_id: redacted,
    deal_id: null,
    person_id: null,
    org_id: null,
    product_id: null,
    activity_id: null,
    lead_id: null,
    add_time: '2023-11-07 07:40:14',
    update_time: '2023-11-07 07:40:14',
    file_name: '6448b025-c4df-4822-bf8a-ecca32b45bcc.jpg',
    file_size: 1859353,
    active_flag: true,
    inline_flag: false,
    remote_location: 's3',
    remote_id: 'company/redacted/user/redacted/files/6448b025-c4df-4822-bf8a-ecca32b45bcc.jpg',
    cid: null,
    s3_bucket: null,
    mail_message_id: null,
    mail_template_id: null,
    deal_name: null,
    person_name: null,
    org_name: null,
    product_name: null,
    lead_name: null,
    url: 'https://app.pipedrive.com/api/v1/files/3077/download',
    name: 'large_image.jpg',
    description: null,
    log_id: null,
    file_type: 'img'
  }
}

Any suggestion where the culprit lies?

Hi @PatsHologram,

regarding your second example with the Pipedrive SDK. The correct parameter names for the addFile method are without underscore, so to make it work you should use:

      const api = new pipedrive.FilesApi(defaultClient);
      const filepath = "./large_image.jpg";
    
      const response = await api.addFile(filepath, {
        dealId: 8834,
      });

All the accepted parameters should be documented in SDK FilesApi docs.

Hope this helps :slight_smile:
David

Hey @david.brnovjak

thx for the feedback.

The Adding a File via Pipedrive API documentation at step 7. Full working example (Node.js) should be updated. There the parameters are with underscores.

Additionally we found the solution for using fetch: don’t set the content type explicitly. We removed

    headers: {
      "Content-Type": "multipart/form-data",
    },

and the upload works fine in our application via the API

Hi,

thanks for reporting. I’ll ask the team to update the docs.

Best regards :slight_smile:
David

Hi! Thanks again for letting us know. The documentation has been updated now.