I’ll try and remember as it was a while back (so details are a bit hazy) but we did find out what was happening. The set up of the Hubspot account meant that we had some Javascript from Hubspot added to our page which was supposed to help with tracking, but it was also intercepting form posts and sending this back to Hubspot as a new contact. So we had the API add a contact and then the JS try and add one as well (or vice versa depending on which one got there first) which was causing contacts to be updated with data from the API to be overwritten by data from the form or being flagged as existing already.
We were using the API as the form had non standard elements that we were dealing with in our BE code. When the JS was sending the form data back, it was guessing what fields on the form contained what data when matching up with the contact fields in Hubspot and guessing wrong, which was causing our data to get messed up. Think in the end we had to enable non-hubspot forms in our settings for it to work (think it was this link Use non-HubSpot forms) and then it started to behave correctly.
Hope this helps!