Why am I Receiving a 405 Issue When Calling the Freshsales API Using Pipedream Proxy Despite Following the Given Structure?

This topic was automatically generated from Slack. You can find the original thread here.

hey guys, getting an issue with the freshsales api using the pipedream proxy. It’s giving me a 405 issue for calling it even though i’m structuring my call just as the api says. More info in the thread

This is my code:

import * as pd from "@pipedream/sdk";

export default async function execute(input) {
  // ------------------------------------------------------
  // 1.  Create the Pipedream backend client
  // ------------------------------------------------------
  const client = pd.createBackendClient({
    environment: process.env.PIPEDREAM_ENVIRONMENT,
    credentials: {
      clientId:     process.env.PIPEDREAM_CLIENT_ID,
      clientSecret: process.env.PIPEDREAM_CLIENT_SECRET,
    },
    projectId: process.env.PIPEDREAM_PROJECT_ID,
  });

  // ------------------------------------------------------
  // 2.  Hard-coded contact data
  // ------------------------------------------------------
  const peopleToCreate = [
    {
      first_name:   "James",
      last_name:    "Sampleton (sample)",
      mobile_number:"1-926-555-9503",
    },
  ];

  // ------------------------------------------------------
  // 3.  Static proxy routing data
  // ------------------------------------------------------
  const proxyRequestOptions = {
    searchParams: {
      account_id:       input.account_id,
      external_user_id: input.external_user_id,
    },
  };

  // ------------------------------------------------------
  // 4.  Fire the parallel POSTs
  // ------------------------------------------------------
  const creationPromises = peopleToCreate.map((person) => {
    const contact = {
      first_name:   person.first_name   ?? undefined,
      last_name:    person.last_name    ?? undefined,
      mobile_number:person.mobile_number?? undefined,
    };

    // Clean payload
    Object.keys(contact).forEach((k) => contact[k] === undefined && delete contact[k]);

    const appRequestConfig = {
      url: "/api/contacts",
      options: {
        method : "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ contact }),
      },
    };

    return client
      .makeProxyRequest(proxyRequestOptions, appRequestConfig)
      .then((data) => ({ status: "success", data, input: person }))
      .catch((err) => ({ status: "error", error: err?.message ?? String(err), input: person }));
  });

  // ------------------------------------------------------
  // 5.  Collate and return
  // ------------------------------------------------------
  const results = await Promise.all(creationPromises);

  return {
    output: {
      created_contacts: results.filter((r) => r.status === "success").map((r) => r.data),
      errors:           results.filter((r) => r.status === "error"),
    },
  };
}

here is the error i’m getting:

 {
        "status": "error",
        "error": "HTTP error! status: 405, body: <html>\r\n<head><title>405 Not Allowed</title></head>\r\n<body>\r\n<center><h1>405 Not Allowed</h1></center>\r\n<hr><center>nginx</center>\r\n</body>\r\n</html>\r\n",
        "input": {
          "first_name": "James",
          "last_name": "Sampleton (sample)",
          "mobile_number": "[1-926-555-9503](tel:1-926-555-9503)"
        }
      }

and this is the docs for the api call i’m trying to make:

Please let me know if this is an issue on my end or if the api is not being passed correctly. I’m using a dynamic url here

Hm I can’t get anything working with their API. cc when you get a chance can you see if you can get a test request working with Freshsales? Looks like our configuration is right, based on their whacky API requirements

LOL yeah their api reqs are kind of weird. thanks for looking into it

Who sends auth via

"Authorization: Token token={api-key}"

:face_palm::skin-tone-2:

Folks, I managed to get it working. Here’re the steps:

  1. On Pipedream, please reconnect your Freshsales account, there’s a new field Bundle Alias (which replaces the domain ). You’ll need to copy the Bundle Alias from the Freshsales UI (1st and 2nd image below)
  2. Then it should work with the Test Connection (Get All Tasks, 3rd image below)
  3. I’ve also updated the app scaffolding, it should work (4th image below)

Amazing Leo tysm for getting it working so quickly! Really appreciate this :slightly_smiling_face:

Ohh was the domain bad? Leo, you might need to update the proxy configuration accordingly also (at the bottom of the admin UI for that app, DM if you have questions)

Thanks for reminding Danny! I’ve sent you a DM

hey guys, quick update here. We were running into some issues with actually getting this to work in the proxy because of the dynamic url. What we figured out is that the actual domain for the freshsales api apparently changed to .myfreshworks.com

Here is a code example of using it with our subdomain

const host = (input.fs_domain ?? process.env.FS_DOMAIN ?? "[retrofix.myfreshworks.com](http://retrofix.myfreshworks.com)").trim();
  const isSuite      = host.endsWith(".[myfreshworks.com](http://myfreshworks.com)");
  const CONTACT_PATH = isSuite ? "/crm/sales/api/contacts" : "/api/contacts";

const res = await client.makeProxyRequest(proxy, {
          url: CONTACT_PATH,
          options: {
            method:  "POST",
            headers: { "Content-Type": "application/json" },
            body:    JSON.stringify(payload),
          },
        });

We had to hard code it in, but the proxy needs to use the dynamic url since they use subdomains. Is the proxy currently using freshsales.io? If so, I believe it should be changed to freshworks. It they were acquired by freshworks

Their API docs are terrible, but where do you see that? Right now the domain we should be using is basically the bundle alias that the user inputs when they connect their account.

They are indeed terrible. I got that just from iterating with ChatGPT and testing lol. This domain worked when the other wasn’t. Let me double check my bundle alias, though, I think that may be the issue