Keep getting error 400 on updated person - but cannot reproduce

Hello there !

I keep getting an error from pipedrive but I cannot reproduce it and I therefore think there might be a bug with pipedrive js client or pipedrive error systems.

I have configured a webhook to call an internal app everythime a person is updated.
My app gets the body from this hook, cleans the data, and makes another update to pipedrive.
An infinite loop is prevented by checking the updated person against the initial one so there are no updates if no changes.

I am monitoring my internal app on datadog and I keep getting errors 400 for some of the calls.
When that happens, I get the body sent via the webhook, put it in postman, call my app, and I get no error = I cannot reproduce.

I have detailed things here : javascript - How can I debug a nestjs application when I cannot reproduce the error locally? - Stack Overflow

Since I cannot reproduce, I am wondering if:

  • the pipedrive js client does not make extra update calls
  • OR the error sent from pipedrive, a bad request with status code 400 is in fact a rate-limit error 429 that is wrongly characterized.

Does someone see a way to solve this issue?

I have already asked pipedrive support who asked me to post my issue here.
I am not a complete beginner = I’m not trying to solve an internal issue, still, there might be something I miss.

Thanks for your help !

list of logs on datadog

the log on datadog

Reproducing with postman with no error

Looking at what you posted on StackOverflow, it looks like the the issue is sending an empty set of fields to update the person record.
I’d say find a way to check whats happening with
const opts = Pipedrive.UpdatePerson.constructFromObject(person); because based on the sentry report, that is empty, which is why Pipedrive is returning a 400 error when you try and update the person again. Try console.log the person and opts objects and see whats going in and out. Maybe isEmpty isn’t picking up the empty hash correctly.

if (Object.keys(person).length == 0) { return true } 

Tip: Set up ngrok (or similar) and add a new webhook to your sandbox account to that address so you can get real pipedrive webhook calls to your development machine, rather than mocking them in Postman.
I’d also suggest if you’re going to respond to the webhook with an outcome message, send it in a json object. Although Pipedrive doesn’t care, and you’d be better sending that outcome as a log event to Datadog instead so its all searchable later.
Something like

{ "entity": "person", "id": 1, "action": "updatePerson", "success": true, "message": "Person data has been cleaned\nNo new email to validate" } 

Hopefully something here will help.

hi @dombarnes and thanks for taking the time.


  • I am testing and making sure the object is not empty, as you can see on stackoverflow I am using lodash isEmpty to make sure of that, and I tested it multiple times, dumped the values to make sure it’s working right
  • Some of the very similar calls work fine, with just to change in code
  • Repeating failed calls does not lead to an error

=> something else is not working

Just threw together a basic test for this based on client-nodejs/ at master · pipedrive/client-nodejs · GitHub which basically seems like the code you’ve used.

The thing I noticed is that constructFromObject doesn’t sanitize the object for invalid parameters. So if you has say

let opts = Pipedrive.UpdatePerson.constructFromObject({
  famous_name: 'Charles'

as your updated person record, it is going to 400 Bad Request, because famous_name isn’t an accepted parameter. So thats my next best guess - the object you’re passing to constructFromObject has some unsupported data in there.
You didn’t post any code to suggest where that’s coming from so I guess its related to some internal data models. You don’t really need to use constructFromObject

apiInstance.updatePerson(1, { name: 'Charlie' }).then((data) => {
  console.log('API called successfully. Returned data: ' + data);
}, (error) => {
1 Like

hi @dombarnes

I hear you.
Unfortunately I do check what fields are sent before passing the object

In my code I am using

    const personDto = pickBy(
      (i, key) =>
        !isEqual(response.personDto[key as keyof IPipedrivePersonDto], body.current[key as keyof PipedrivePerson]) &&
        Object.values(dtoKeys).includes(key as PipedrivePersonFieldsKeys),

and dtoFields is defined like this

export const dtoKeys = [
  PipedrivePersonFieldsKeys.Name, //name is cleant
  PipedrivePersonFieldsKeys.Email, //email is enriched
  PipedrivePersonFieldsKeys.Phone, //phone is cleant
  PipedrivePersonFieldsKeys.JobTitle, //job title ans position are merged
  PipedrivePersonFieldsKeys.PositionInCompany, //job title ans position are merged
  PipedrivePersonFieldsKeys.Linkedin, //url is cleant
  PipedrivePersonFieldsKeys.Pipeline, //lemlist campaigns are updated
  PipedrivePersonFieldsKeys.Stage, //lemlist campaigns are updated
  PipedrivePersonFieldsKeys.EmailVerification, //lemlist campaign are updated
  PipedrivePersonFieldsKeys.Unsubscribed, //lemlist campaign are updated
  PipedrivePersonFieldsKeys.Language, //lemlist campaign are updated

All the fields can be updated, which I can do via Postman

Please pipedive guys: can you look in your logs what the data about this issue is? Can you check whether you are not sending a code 400 instead of a code 429?

Hey @Sebastien_Vassaux
Thanks for detailing the issue. I see a lot of good points in the thread. However, we can look at it from our side to figure out if there’s something wrong on Pipedrive’s side

I have reached out to you via DM for further details about the account.

This topic was automatically closed after 10 days. New replies are no longer allowed.