Multiple email ids are added to same contact at hubspot

Hi Team,

We are facing an issue with Hubspot’s contact APIs we are using. Few different contacts which we are trying to create at Hubspot are getting updated against same entity at Hubspot.

For example, three different contacts from our source with email ids – ‘angel.0114@yahoo.com’, ‘kellyannchapa@gmail.com’, ‘jenaaso@gmail.com’ are updated against same entity with vid – ‘50945314’ at Hubspot end using the create API. The API key used for the update is [redacted].

Below is the screenshot for the same -

[

SS_Hubspot_CreateAPI_Issue.JPG1304×658 76.9 KB

](https://community.hubspot.com/legacyfs/online/uploads/default/original/2X/e/e1b4dc61e340859ebe20e7dd4703f77f2c8b6790.jpeg)

As per the documentation for contacts API, email address is treated as primary key. In that case, once the email id is different, a new entity is supposed to be created at Hubspot but instead it is getting mapped to the same contact entity at hubspot.

Please check for the same and revert. Also please let us know if any further details are required.

Welcome, @deepak.patro.

Do not include API keys in your responses. This is a public forum and anyone can access your account with that key. I’ve removed the key from your initial post. For your security, please immediately deactivate that API key and create a new one.

I cannot revert this behavior, but I am happy to investigate why a single contact record is being updated. Please share the endpoint URL you are using (do not include the API key) and the request bodies you are sending.

For example, providing a different email to this endpoint will create a new contact record, but using a vid in this endpoint will not.

I need to see the full picture of the information you are sending into HubSpot.

Apologies for adding API key to the query. I felt it must be needed for your investigation. I will refrain from passing the same going forward.

Here is the API we used to create a contact. Request body is created internally through our scheduled job. Hence I could not get the actual request body. But here are the request bodies manually created as per the logic -

For first user - ‘angel.0114@yahoo.com’

{
 "properties": [
 {
 "property": "address",
 "value": "404 N Luque St"
 },
 {
 "property": "cbcs_expiration_date",
 "value": null
 },
 {
 "property": "cbcs_pass_date",
 "value": null
 },
 {
 "property": "cbcs_recertification_date",
 "value": null
 },
 {
 "property": "ccma_expiration_date",
 "value": "03/16/2020"
 },
 {
 "property": "ccma_pass_date",
 "value": "03/16/2018"
 },
 {
 "property": "ccma_recertification_date",
 "value": null
 },
 {
 "property": "cehrs_expiration_date",
 "value": null
 },
 {
 "property": "cehrs_recertification_date",
 "value": null
 },
 {
 "property": "cet_expiration_date",
 "value": null
 },
 {
 "property": "cet_pass_date",
 "value": null
 },
 {
 "property": "cet_recertification_date",
 "value": null
 },
 {
 "property": "chers_pass_date",
 "value": null
 },
 {
 "property": "city",
 "value": "Sinton"
 },
 {
 "property": "cmaa_expiration_date",
 "value": null
 },
 {
 "property": "cmaa_pass_date",
 "value": null
 },
 {
 "property": "cmaa_recertification_date",
 "value": null
 },
 {
 "property": "cpct_a_expiration_date",
 "value": null
 },
 {
 "property": "cpct_a_pass_date",
 "value": null
 },
 {
 "property": "cpct_a_recertification_date",
 "value": null
 },
 {
 "property": "cpt_expiration_date",
 "value": null
 },
 {
 "property": "cpt_pass_date",
 "value": null
 },
 {
 "property": "cpt_recertification_date",
 "value": null
 },
	{
 "property": "email",
 "value": "angel.0114@yahoo.com"
 },
	{
 "property": "cert_holder_unique_id",
 "value": "9569406"
 },
 {
 "property": "excpt_expiration_date",
 "value": null
 },
 {
 "property": "excpt_pass_date",
 "value": null
 },
 {
 "property": "excpt_recertification_date",
 "value": null
 },
 {
 "property": "firstname",
 "value": "Angelica"
 },
 {
 "property": "lastname",
 "value": "Palomo"
 },
 {
 "property": "latest_certification_action_date",
 "value": "03/16/2018"
 },
 {
 "property": "old_nha_chi_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_chi_pass_date",
 "value": null
 },
 {
 "property": "old_nha_chi_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_expiration",
 "value": null
 },
 {
 "property": "old_nha_chuc_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_pass_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_corst_pass_date",
 "value": null
 },
 {
 "property": "old_nha_corst_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_recertification_date",
 "value": null
 },
 {
 "property": "phone",
 "value": "+1 361-437-9847"
 },
 {
 "property": "state",
 "value": "TX"
 },
 {
 "property": "zip",
 "value": "78387"
 },
 {
 "property": "next_cbcs_exam_date",
 "value": null
 },
 {
 "property": "next_ccma_exam_date",
 "value": null
 },
 {
 "property": "next_cehrs_exam_date",
 "value": null
 },
 {
 "property": "next_cet_exam_date",
 "value": null
 },
 {
 "property": "next_cmaa_exam_date",
 "value": null
 },
 {
 "property": "next_cpct_a_exam_date",
 "value": null
 },
 {
 "property": "next_cpt_exam_date",
 "value": null
 },
 {
 "property": "next_excpt_exam_date",
 "value": null
 },
 {
 "property": "cbcs_exam_attempts",
 "value": null
 },
 {
 "property": "ccma_exam_attempts",
 "value": "1"
 },
 {
 "property": "cehrs_exam_attempts",
 "value": null
 },
 {
 "property": "cet_exam_attempts",
 "value": null
 },
 {
 "property": "cmaa_exam_attempts",
 "value": null
 },
 {
 "property": "cpct_a_exam_attempts",
 "value": null
 },
 {
 "property": "cpt_exam_attempts",
 "value": null
 },
 {
 "property": "excpt_exam_attempts",
 "value": null
 },
 {
 "property": "number_of_active_certifications",
 "value": "1"
 },
 {
 "property": "number_of_certifications_eligible_for_reinstatement",
 "value": "0"
 },
 {
 "property": "number_of_lapsed_certifications",
 "value": "0"
 },
 {
 "property": "birthdate",
 "value": "1997-01-14"
 },
 {
 "property": "gender",
 "value": "F"
 },
 {
 "property": "chi_exam_attempts",
 "value": null
 },
 {
 "property": "chuc_exam_attempts",
 "value": null
 },
 {
 "property": "cmht_exam_attempts",
 "value": null
 },
 {
 "property": "cmla_exam_attempts",
 "value": null
 },
 {
 "property": "cmt_exam_attempts",
 "value": null
 },
 {
 "property": "corst_exam_attempts",
 "value": null
 },
 {
 "property": "cpe_exam_attempts",
 "value": null
 }
 ]
}

For second user - ‘kellyannchapa@gmail.com’

{
 "properties": [
 {
 "property": "address",
 "value": "1207 E. Mesquite"
 },
 {
 "property": "cbcs_expiration_date",
 "value": "07/12/2020"
 },
 {
 "property": "cbcs_pass_date",
 "value": "07/12/2018"
 },
 {
 "property": "cbcs_recertification_date",
 "value": null
 },
 {
 "property": "ccma_expiration_date",
 "value": null
 },
 {
 "property": "ccma_pass_date",
 "value": null
 },
 {
 "property": "ccma_recertification_date",
 "value": null
 },
 {
 "property": "cehrs_expiration_date",
 "value": null
 },
 {
 "property": "cehrs_recertification_date",
 "value": null
 },
 {
 "property": "cet_expiration_date",
 "value": null
 },
 {
 "property": "cet_pass_date",
 "value": null
 },
 {
 "property": "cet_recertification_date",
 "value": null
 },
 {
 "property": "chers_pass_date",
 "value": null
 },
 {
 "property": "city",
 "value": "Kingsville"
 },
 {
 "property": "cmaa_expiration_date",
 "value": null
 },
 {
 "property": "cmaa_pass_date",
 "value": null
 },
 {
 "property": "cmaa_recertification_date",
 "value": null
 },
 {
 "property": "cpct_a_expiration_date",
 "value": null
 },
 {
 "property": "cpct_a_pass_date",
 "value": null
 },
 {
 "property": "cpct_a_recertification_date",
 "value": null
 },
 {
 "property": "cpt_expiration_date",
 "value": null
 },
 {
 "property": "cpt_pass_date",
 "value": null
 },
 {
 "property": "cpt_recertification_date",
 "value": null
 },
	{
 "property": "email",
 "value": "kellyannchapa@gmail.com"
 },
	{
 "property": "cert_holder_unique_id",
 "value": "9613651"
 },
 {
 "property": "excpt_expiration_date",
 "value": null
 },
 {
 "property": "excpt_pass_date",
 "value": null
 },
 {
 "property": "excpt_recertification_date",
 "value": null
 },
 {
 "property": "firstname",
 "value": "Kelly"
 },
 {
 "property": "lastname",
 "value": "Chapa"
 },
 {
 "property": "latest_certification_action_date",
 "value": "07/12/2018"
 },
 {
 "property": "old_nha_chi_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_chi_pass_date",
 "value": null
 },
 {
 "property": "old_nha_chi_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_expiration",
 "value": null
 },
 {
 "property": "old_nha_chuc_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_pass_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_corst_pass_date",
 "value": null
 },
 {
 "property": "old_nha_corst_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_recertification_date",
 "value": null
 },
 {
 "property": "phone",
 "value": "+1 361-455-9560"
 },
 {
 "property": "state",
 "value": "TX"
 },
 {
 "property": "zip",
 "value": "78363"
 },
 {
 "property": "next_cbcs_exam_date",
 "value": null
 },
 {
 "property": "next_ccma_exam_date",
 "value": null
 },
 {
 "property": "next_cehrs_exam_date",
 "value": null
 },
 {
 "property": "next_cet_exam_date",
 "value": null
 },
 {
 "property": "next_cmaa_exam_date",
 "value": null
 },
 {
 "property": "next_cpct_a_exam_date",
 "value": null
 },
 {
 "property": "next_cpt_exam_date",
 "value": null
 },
 {
 "property": "next_excpt_exam_date",
 "value": null
 },
 {
 "property": "cbcs_exam_attempts",
 "value": "1"
 },
 {
 "property": "ccma_exam_attempts",
 "value": null
 },
 {
 "property": "cehrs_exam_attempts",
 "value": null
 },
 {
 "property": "cet_exam_attempts",
 "value": null
 },
 {
 "property": "cmaa_exam_attempts",
 "value": null
 },
 {
 "property": "cpct_a_exam_attempts",
 "value": null
 },
 {
 "property": "cpt_exam_attempts",
 "value": null
 },
 {
 "property": "excpt_exam_attempts",
 "value": null
 },
 {
 "property": "number_of_active_certifications",
 "value": "1"
 },
 {
 "property": "number_of_certifications_eligible_for_reinstatement",
 "value": "0"
 },
 {
 "property": "number_of_lapsed_certifications",
 "value": "0"
 },
 {
 "property": "birthdate",
 "value": "1972-05-10"
 },
 {
 "property": "gender",
 "value": "F"
 },
 {
 "property": "chi_exam_attempts",
 "value": null
 },
 {
 "property": "chuc_exam_attempts",
 "value": null
 },
 {
 "property": "cmht_exam_attempts",
 "value": null
 },
 {
 "property": "cmla_exam_attempts",
 "value": null
 },
 {
 "property": "cmt_exam_attempts",
 "value": null
 },
 {
 "property": "corst_exam_attempts",
 "value": null
 },
 {
 "property": "cpe_exam_attempts",
 "value": null
 }
 ]
}

For third user - ‘jenaaso@gmail.com’

{
 "properties": [
 {
 "property": "address",
 "value": "121 Opal Dr"
 },
 {
 "property": "cbcs_expiration_date",
 "value": null
 },
 {
 "property": "cbcs_pass_date",
 "value": null
 },
 {
 "property": "cbcs_recertification_date",
 "value": null
 },
 {
 "property": "ccma_expiration_date",
 "value": "08/10/2020"
 },
 {
 "property": "ccma_pass_date",
 "value": "08/10/2018"
 },
 {
 "property": "ccma_recertification_date",
 "value": null
 },
 {
 "property": "cehrs_expiration_date",
 "value": null
 },
 {
 "property": "cehrs_recertification_date",
 "value": null
 },
 {
 "property": "cet_expiration_date",
 "value": null
 },
 {
 "property": "cet_pass_date",
 "value": null
 },
 {
 "property": "cet_recertification_date",
 "value": null
 },
 {
 "property": "chers_pass_date",
 "value": null
 },
 {
 "property": "city",
 "value": "Corpus Christi"
 },
 {
 "property": "cmaa_expiration_date",
 "value": null
 },
 {
 "property": "cmaa_pass_date",
 "value": null
 },
 {
 "property": "cmaa_recertification_date",
 "value": null
 },
 {
 "property": "cpct_a_expiration_date",
 "value": null
 },
 {
 "property": "cpct_a_pass_date",
 "value": null
 },
 {
 "property": "cpct_a_recertification_date",
 "value": null
 },
 {
 "property": "cpt_expiration_date",
 "value": null
 },
 {
 "property": "cpt_pass_date",
 "value": null
 },
 {
 "property": "cpt_recertification_date",
 "value": null
 },
	{
 "property": "email",
 "value": "jenaaso@gmail.com"
 },
	{
 "property": "cert_holder_unique_id",
 "value": "9626484"
 },
 {
 "property": "excpt_expiration_date",
 "value": null
 },
 {
 "property": "excpt_pass_date",
 "value": null
 },
 {
 "property": "excpt_recertification_date",
 "value": null
 },
 {
 "property": "firstname",
 "value": "Adrian"
 },
 {
 "property": "lastname",
 "value": "Mott"
 },
 {
 "property": "latest_certification_action_date",
 "value": null
 },
 {
 "property": "old_nha_chi_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_chi_pass_date",
 "value": null
 },
 {
 "property": "old_nha_chi_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_expiration",
 "value": null
 },
 {
 "property": "old_nha_chuc_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_pass_date",
 "value": null
 },
 {
 "property": "old_nha_chuc_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmht_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmla_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cmt_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_corst_pass_date",
 "value": null
 },
 {
 "property": "old_nha_corst_recertification_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_expiration_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_pass_date",
 "value": null
 },
 {
 "property": "old_nha_cpe_recertification_date",
 "value": null
 },
 {
 "property": "phone",
 "value": "555-122-2323"
 },
 {
 "property": "state",
 "value": "MA"
 },
 {
 "property": "zip",
 "value": "02139"
 },
 {
 "property": "next_cbcs_exam_date",
 "value": null
 },
 {
 "property": "next_ccma_exam_date",
 "value": null
 },
 {
 "property": "next_cehrs_exam_date",
 "value": null
 },
 {
 "property": "next_cet_exam_date",
 "value": null
 },
 {
 "property": "next_cmaa_exam_date",
 "value": null
 },
 {
 "property": "next_cpct_a_exam_date",
 "value": null
 },
 {
 "property": "next_cpt_exam_date",
 "value": null
 },
 {
 "property": "next_excpt_exam_date",
 "value": null
 },
 {
 "property": "cbcs_exam_attempts",
 "value": null
 },
 {
 "property": "ccma_exam_attempts",
 "value": null
 },
 {
 "property": "cehrs_exam_attempts",
 "value": null
 },
 {
 "property": "cet_exam_attempts",
 "value": null
 },
 {
 "property": "cmaa_exam_attempts",
 "value": null
 },
 {
 "property": "cpct_a_exam_attempts",
 "value": null
 },
 {
 "property": "cpt_exam_attempts",
 "value": null
 },
 {
 "property": "excpt_exam_attempts",
 "value": null
 },
 {
 "property": "number_of_active_certifications",
 "value": null
 },
 {
 "property": "number_of_certifications_eligible_for_reinstatement",
 "value": null
 },
 {
 "property": "number_of_lapsed_certifications",
 "value": null
 },
 {
 "property": "birthdate",
 "value": null
 },
 {
 "property": "gender",
 "value": null
 },
 {
 "property": "chi_exam_attempts",
 "value": null
 },
 {
 "property": "chuc_exam_attempts",
 "value": null
 },
 {
 "property": "cmht_exam_attempts",
 "value": null
 },
 {
 "property": "cmla_exam_attempts",
 "value": null
 },
 {
 "property": "cmt_exam_attempts",
 "value": null
 },
 {
 "property": "corst_exam_attempts",
 "value": null
 },
 {
 "property": "cpe_exam_attempts",
 "value": null
 }
 ]
}

Please let me know if there are any further details required.

Hi, @deepak.patro.

Thank you for that information.

This contact record shows updates from this batch endpoint, not the Create a new contact endpoint.

This is evident through the change source “Bulk edit” in the email property’s history:

[

Bulk edit.jpg1063×803 128 KB

](https://community.hubspot.com/legacyfs/online/uploads/default/original/2X/c/cbb17f2ac82232b6177c55dcf7444d4c818f2f58.jpeg)

Per the batch endpoint documentation, either a vid or email address must be included with each set of property data. Please note that these fields should be outside the properties array:

[

Include email outside properties array.jpg934×408 73.7 KB

](https://community.hubspot.com/legacyfs/online/uploads/default/original/2X/8/8be39d9945f22467caa9e5038e7d180ebb4eb9c8.jpeg)

Your examples show the email property inside the properties array. Since you are not receiving errors but you are seeing the same contact record updated multiple times, the same vid must be included in multiple calls.

Through my testing, I’ve confirmed that this is the only scenario that would update a single record with multiple email addresses. Other combinations either fail and throw errors or create multiple contacts.

I recommend taking the following steps:

  1. Checking whether you are caching or including the vid 50945314 in these batch calls outside of the properties array.
  2. Include the email address outside the properties array instead of inside. See the example below:
 {
 "email": "contact.1234@example.com",
 "properties": [
 {
 "property": "firstname",
 "value": "Example"
 },
 {
 "property": "lastname",
 "value": "Contact"
 }
 ]
 }
]

Thanks for your response.

The request bodies shared above were only for the initial call while creating a contact. Once a contact gets created at Hubspot, we are storing the vid of that contact from the response of that API and using that vid in batch update along with other contacts in subsequent calls. The request body for bulk update will be generated as follows -

[{"vid": "1234567","properties": [{"property": "firstname","value": "Harper"},{"property": "lastname","value": "Wolfberg"},...]},{"vid": "2345678","properties": [{"property": "firstname","value": "Codey"},{"property": "lastname","value": "Huang"},...]},...]

The updates you spotted in the property’s history must be referring to those batch update calls. But I am not sure if the batch update is updating the email of that contact by itself. Since our approach has no such scope.

Our approach to create or update contacts is as follows. We have a source database with different contacts. We have a daily job which fetches the contacts from the source and updates them to Hubspot. The job stores the vids of the contacts which get created initially using create API call. For the subsequent runs of that job, all the contacts which are already stored will be attempted for update at Hubspot using batch update API. Any new contacts from the source will be attempted in create API again.

In case if we lose some mappings from our local storage, our job will attempt to create a entry for a contact which is already existing in Hubspot. If that happens, Hubspot’s create API will respond back with error code 409 stating that ‘Contact already exists’ and the vid for that existing contact. In such case, we create a mapping for that vid and contact again assuming that it is a contact which already is present at Hubspot but got lost from the mappings in our storage.

For ex -

For first run, if we have one user A with email ‘a_user@mail.com’ in our source. We attempt to create corresponding entry at Hubspot using create API. Let’s say the vid for that contact at Hubspot is created as ‘1234567’. At our local storage, we add the mapping for email ‘a_user@mail.com’ with vid ‘1234567’.
For next run, suppose we got one new user B in the source with email - ‘b_user@mail.com’ along with the existing user A. So for this run, while we check the storage, we get only user A’s mapping since user A is already added to the storage but B is not. So we will attempt to create a entry at Hubspot for the user B using create API and attempt to update user A at Hubspot using batch update API. Let’s say the vid for that user B at Hubspot is created as ‘2345678’. At our local storage, we add the mapping for email ‘b_user@mail.com’ with vid ‘2345678’.
For third run, suppose if we lost data for user B in our local storage. So for this run, while we check the storage, we only get user A’s information. So we again attempt to create a entry at Hubspot for the user B using create API and attempt to update user A at Hubspot using batch update API. But since user B is already existing at Hubspot, create API will respond with code 409 along with vid - ‘2345678’. So we now add the mapping for email ‘b_user@mail.com’ with vid ‘2345678’ again which was missing.

We create mappings for vid whenever error code 409 is received, under the assumption that Hubspot does not allow update of email ids and that this error is possible only when a contact got created in Hubspot but that got lost in our mappings. But I could see multiple mappings getting created in our storage for same vid which is incorrect. This is possible only in two cases -

  • If the create API call for two different users respond back with same vid and corresponding mappings get created for those users with same vid.

For ex -

For fourth run, suppose there is a new user C in the source with email - ‘c_user@mail.com’ along with the existing users A and B. While we check the storage, we will get mappings for user A and B. So we attempt to create a entry at Hubspot for the user C using create API and attempt to update users A and B at Hubspot using batch update API. But if create API call for user C responds with the same vid of user A - ‘1234567’. So as per our implementation, we add this mapping for our email - ‘c_user@mail.com’ with the vid - ‘1234567’. So in our storage, we will have two mappings for vid - ‘1234567’ against email ids - ‘a_user@mail.com’ and ‘c_user@mail.com’.

  • If the user updates email id to that of another new user in Hubspot UI, which will cause create API call of new user to fail with 409 code and corresponding mapping gets created for that new user with the same vid.

For ex -

For fourth run, suppose there is a new user C in the source with email - ‘c_user@mail.com’ along with the existing users A and B. And meanwhile in hubspot UI, the user A changed its email id to that of user C - ‘c_user@mail.com’. While we check the storage, we will get mappings for user A and B. So we again attempt to create a entry at Hubspot for the user C using create API and attempt to update users A and B at Hubspot using batch update API.
So create API call for user C will respond with code 409 and vid of user A - ‘1234567’ since the email id ‘c_user@mail.com’ is already existing at Hubspot now for user A. So as per our implementation, we add this mapping for our email - ‘c_user@mail.com’ with the vid - ‘1234567’. So in our storage, we will have two mappings for vid - ‘1234567’ against email ids - ‘a_user@mail.com’ and ‘c_user@mail.com’ which is incorrect.

In both the cases, for all subsequent runs of the job, one of the two entries for that vid will be picked and will be updated at Hubspot in batch update calls. These updates are the ones which are reflecting under email property’s history as per my assumption.

Else, there is no possibility that multiple mappings get created for same vid in our storage in the first place. And if that is not possible, our job won’t attempt to update different emails for that same vid in batch updates.

Thanks for your response.

The request bodies shared above were only for the initial call while creating a contact. Once a contact gets created at Hubspot, we are storing the vid of that contact from the response of that API and using that vid in Batch Update along with other contacts in subsequent calls. The request body for bulk update will be generated as follows -

[{
		"vid": "1234567",
		"properties": [{
				"property": "firstname",
				"value": "Harper"
			},
			{
				"property": "lastname",
				"value": "Wolfberg"
			},
 ...
		]
	},
	{
		"vid": "2345678",
		"properties": [{
				"property": "firstname",
				"value": "Codey"
			},
			{
				"property": "lastname",
				"value": "Huang"
			},
 ...
		]
	},
 	...
]

The updates you spotted in the property’s history must be referring to those batch update calls. But I am not sure if the batch update is updating the email of that contact by itself. Since our approach has no such scope.

Our approach to create or update contacts is as follows. We have a source database with different contacts. We have a daily job which fetches the contacts from the source and updates them to Hubspot. The job stores the vids of the contacts which get created initially using create API call. For the subsequent runs of that job, all the contacts which are already stored will be attempted for update at Hubspot using batch update API. Any new contacts from the source will be attempted in create API again.

In case if we lose some mappings from our local storage, our job will attempt to create a entry for a contact which is already existing in Hubspot. If that happens, Hubspot’s create API will respond back with error code 409 stating that ‘Contact already exists’ and the vid for that existing contact. In such case, we create a mapping for that vid and contact again assuming that it is a contact which already is present at Hubspot but got lost from the mappings in our storage.

For ex -

For first run, if we have one user A with email 'a_user@mail.com' in our source. We attempt to create corresponding entry at Hubspot using create API. Let's say the vid for that contact at Hubspot is created as '1234567'. At our local storage, we add the mapping for email 'a_user@mail.com' with vid '1234567'. 

For next run, suppose we got one new user B in the source with email - 'b_user@mail.com' along with the existing user A. So for this run, while we check the storage, we get only user A's mapping since user A is already added to the storage but B is not. So we will attempt to create a entry at Hubspot for the user B using create API and attempt to update user A at Hubspot using batch update API. Let's say the vid for that user B at Hubspot is created as '2345678'. At our local storage, we add the mapping for email 'b_user@mail.com' with vid '2345678'.

For third run, suppose if we lost data for user B in our local storage. So for this run, while we check the storage, we only get user A's information. So we again attempt to create a entry at Hubspot for the user B using create API and attempt to update user A at Hubspot using batch update API. But since user B is already existing at Hubspot, create API will respond with code 409 along with vid - '2345678'. So we now add the mapping for email 'b_user@mail.com' with vid '2345678' again which was missing.

We create mappings for vid whenever error code 409 is received, under the assumption that Hubspot does not allow update of email ids and that this error is possible only when a contact got created in Hubspot but that got lost in our mappings. But I could see multiple mappings getting created in our storage for same vid which is incorrect. This is possible only in two cases -

  • If the create API call for two different users respond back with same vid and corresponding mappings get created for those users with same vid.

For ex -

For fourth run, suppose there is a new user C in the source with email - 'c_user@mail.com' along with the existing users A and B. While we check the storage, we will get mappings for user A and B. So we attempt to create a entry at Hubspot for the user C using create API and attempt to update users A and B at Hubspot using batch update API. But if create API call for user C responds with the same vid of user A - '1234567'. So as per our implementation, we add this mapping for our email - 'c_user@mail.com' with the vid - '1234567'. So in our storage, we will have two mappings for vid - '1234567' against email ids - 'a_user@mail.com' and 'c_user@mail.com'.

  • If the user updates email id to that of another new user in Hubspot UI, which will cause create API call of new user to fail with 409 code and corresponding mapping gets created for that new user with the same vid.

For ex -

For fourth run, suppose there is a new user C in the source with email - 'c_user@mail.com' along with the existing users A and B. And meanwhile in hubspot UI, the user A changed its email id to that of user C - 'c_user@mail.com'. While we check the storage, we will get mappings for user A and B. So we again attempt to create a entry at Hubspot for the user C using create API and attempt to update users A and B at Hubspot using batch update API. 

So create API call for user C will respond with code 409 and vid of user A - '1234567' since the email id 'c_user@mail.com' is already existing at Hubspot now for user A. So as per our implementation, we add this mapping for our email - 'c_user@mail.com' with the vid - '1234567'. So in our storage, we will have two mappings for vid - '1234567' against email ids - 'a_user@mail.com' and 'c_user@mail.com'.

In both the cases, for all subsequent runs of the job, one of the two entries for that vid will be picked and will be updated at Hubspot in batch update calls. These updates are the ones which are reflecting under email property’s history as per my assumption.

Else, there is no possibility that multiple mappings get created for same vid in our storage in the first place. And if that is not possible, our job won’t attempt to update different emails for that same vid in batch updates.

Hi Team,

Can you please update on this thread. Please let me know if there are any inputs needed from me.

Thanks

Hi, @deepak_patro.

Sincere apologies for the delayed response.

To be transparent, I missed your reply. This is partially because I was not tagged in any of the posts. It’s really easy for these kinds of replies to fall through the cracks, so please tag me in future messges with @IsaacTakushi.

Thank you for including all this detail!

While this gives me insight into your processes, the data on my end tells a different story.

This contact record’s email property history shows no sign of the endpoint you claim is used to initially create contacts. Instead, the contact was both created and repeatedly updated with the batch create or update endpoint.

In your last message, you said:

“The updates you spotted in the property’s history must be referring to those batch update calls. But I am not sure if the batch update is updating the email of that contact by itself. Since our approach has no such scope.”

This conclusion is not supported by the contact’s data. The UI property history shows the very first email value set for the contact:

These changes are also visible in the contact’s JSON data. If you use the endpoint URL:

https://api.hubapi.com/contacts/v1/contact/vid/50945314/profile?propertyMode=value_and_history&hapikey=your_key

you will see a wealth of explicit updates to the contact’s email property, exclusively from the BATCH_UPDATE endpoint. The first of these is:

{
"value": "a...@yahoo.com",
"source-type": "BATCH_UPDATE",
"source-id": null,
"source-label": null,
"timestamp": 1550149286757,
"selected": false
}

This data to points to some problematic logic on your end. Somehow, vid 50945314 (and likely others) are being used repeatedly, resulting in new email addresses being placed on existing records. Per my last response, I’ve confirmed that this is the only scenario that would update a single record with multiple email addresses when the BATCH_UPDATE endpoint is used. Other combinations either fail and throw errors or create multiple contacts.

I won’t be able to troubleshoot logic on your end, but all evidence suggests that the Contacts API’s batch create or update endpoint is working properly.

Thanks @IsaacTakushi for your reply.

Even I could not see the first update with create contact API call as I expected from my application. The evidence you shared is valid. This is strange for me as our current implementation has no such scope. Without creating a contact, it cannot start updating the same.

I have tried to replicate the same in other account we use for DEV as well. But I could not reproduce the issue. It must be probably because I used the expected steps one after the other and as per your API’s behavior, it created separate entities.

This might be a rare scenario where there is some manual addition/update to the contact in Hubspot even before our application tried to create it. I will investigate further on this case and try to find out the possibililty. Can you please help me in understanding the below scenario.

I can see the first update on the email property was on 2/17/2019, but the job, through which we update, was running since 2018. We can assume that this contact got added in our source itself on 2/17/2019, but contact’s overall activity history was available from November 2016. This either implies that

  • the contact was created manually along with the email property in 2016 long before our application tried to create it

or

  • the contact was created in 2016 without the email property and our job tried to add the email property 2018 onwards.

The second case should not be possible as per my knowledge since email is mandatory for a contact. So can you please check and let me know if there is a possibility if a contact can be created manually without an email id. If not, can you check if there is a possiblilty that the email property’s history before 2/17/2019 got erased and the property’s creation also got erased along with that.

It’s good to hear from you, @deepak_patro. You bring up some good points.

Looking into this contact’s JSON data (accessible via this endpoint), the earliest date I can find is corresponds to the createdate value of 1521235690999, which is 16 March 2018 at 5:28:10 PM UTC-04:00. This contact originated from a form with the GUID 46bb7f11-232a-469d-8121-6c912e43d0e2. This form no longer exists in account 1430252 and is no longer visible or retrievable from my back end tools.

Unfortunately, I also don’t have insight into the past email property history. This must have been set at the time, since this setting allowing forms to accept submissions without email addresses had not yet been released.

It was possible to manually create contacts without email addresses before March 2018, however I would expect to see a CRM_UI source-type in the contact’s JSON data instead of FORM.

Hi @IsaacTakushi ,

Thanks for your inputs.

It does look like a one-off issue where the contact had some manual update. I checked my entire code. As I shared earlier, our application does below three steps only

  • If a email id is not already present in Hubspot, it creates a new contact at Hubspot and stores its reference.
  • If a email id is already existing at Hubspot, it updates it at Hubspot.
  • If a reference of already created contact is missing or a contact with email id is manually created at Hubspot, it stores its reference upon receiving failure.

Nowhere I could see a possibililty where our application can update more than one email id against same contact (vid) at Hubspot.

My assumption of what must have happened -

  1. Contact must have been created with email id - ‘jenaaso@gmail.com’ initially either through our job or manually through UI.
  2. If it was through our job, it must have stored its reference vid - ‘50945314’ against email id - ‘jenaaso@gmail.com’ at our end. If it was through UI, it must have received 409 (Contact already exists) error while attempting create request and then it must have added reference vid - ‘50945314’ against email id - ‘jenaaso@gmail.com’.
  3. Then the email ids - ‘angel.0114@yahoo.com’ and ‘kellyannchapa@gmail.com’ must have been appended manually to the same contact.
  4. Following that those two emailds might have got added in our source and our job might have attempted to create both (‘angel.0114@yahoo.com’ and ‘kellyannchapa@gmail.com’) and update the already added one (‘jenaaso@gmail.com’).
  5. The create attempts must have failed with 409 error and hence our job might have stored its references sent in the error response against respective email ids, which is the same vid - ‘50945314’.
  6. So in subsequent runs of our job, it must have been attempting to update all three email ids against the same contact at Hubspot.

So can you please remove the secondary email ids ‘angel.0114@yahoo.com’ and ‘kellyannchapa@gmail.com’ from this contact as I don’t have permission for the same and I will delete their respective references at our end. Then I hope our job will treat those email ids as new unique ones and will attempt to create the same in its subsequent runs. Hopefully it will not receive 409 errors this time and hence it will successfully create separate new contacts for these two email ids.

Hi, @deepak_patro.

That scenario makes sense to me.

I’ve removed angel...@yahoo.com and kellyann...@gmail.com as secondary email addresses of this contact record. While the values are still visible in the email property’s history, hopefully they won’t affect your efforts to correct the data.

Please let me know how this goes!

Hi @IsaacTakushi ,

The correction went fine. Now I can see there are three different contacts at Hubspot with three different vids.

Thanks a lot for your time and support in analyzing the issue

Hooray! Happy to help, @deepak_patro!