Insert or Update (upsert)

Purpose

To insert or update a record. The system checks for duplicate records based on the duplicate check field's values. If the record is already present, it gets updated. If not, the record is inserted.

Request URL

https://www.zohoapis.com/crm/v2/{module_api_name}/upsert

module_api_name - The API name of the module

Modules supported in Get List of Records are supported here.

Request Method

POST

Scope

scope=ZohoCRM.modules.all
(or)
scope=ZohoCRM.modules.{module_name}.{operation_type}

Possible module namesPossible operation types
leads, accounts, contacts, deals, campaigns, cases, solutions, products, vendors, pricebooks, quotes, salesorders, purchaseorders, invoices, custom, and notesALL - Full access to all the records in the module
WRITE - Edit records in the module
CREATE - Create records in the module
Note:
  • The system checks for duplicate records based on the duplicate check field's values. There are two types of duplicate check fields:
    • The system-defined duplicate check fields - Certain system-generated fields are marked as unique, by default. When you upsert a record, the system checks for duplicate entries in these fields. Click here to know the module-wise system-defined duplicate check fields.
    • The user-defined unique fields - The fields for which "Do not allow duplicate values" is enabled. Click here to know more.
  • You can set the order in which the system checks for duplicate records by specifying the duplicate_check_field array in the input. Note that you can add only system-defined duplicate check fields and user-defined unique fields to the duplicate_check_field array.

    Example for the Leads module:

    "duplicate_check_fields": [
    "Email",
    "Phone",
    "Fax"
    ]

    Here, "Email" is the system-defined duplicate check field, and "Phone" and "Fax" are the user-defined unique fields for the Leads module.

  • If you do not specify the duplicate_check_fields, the system checks for duplicate records in this order: system-defined duplicate check fields > user-defined unique fields.

How does the duplicate check work?

Consider a case where the user has configured two unique fields unique1 and unique2 for a module (user-defined unique fields), and Email is a system-defined unique field.
The following table explains how the duplicate check happens for different user inputs to the duplicate_check_fields array.

User Input to the "duplicate_check_fields" ArrayDuplicate Check Pattern
unique1unique1, unique2
unique2unique2, unique1
unique1, unique2unique1, unique2
EmailEmail, unique1, unique2
No inputSystem-defined duplicate check field for that module followed by unique fields. That is, Email, unique1, unique2

If you do not specify system-defined duplicate check fields in the array, the system will ignore them and check only for user-defined unique fields.

Possible Errors

HTTP StatusError CodeMessageReason
400INVALID_MODULEThe module name given seems to be invalidInvalid module name or no tab permission, or the module could have been removed from the organized module
400INVALID_MODULEThe given module is not supported in APIThe modules such as Documents and Projects are not supported in the current API. (This error will not be shown, once these modules are supported.)

Note:

  • The system throws an error if the field value length exceeds the maximum length defined for that field.

  • If an API is used inside a Function and the field value length exceeds the limit, then that function receives an error response from the API. For ex: If the max length for a "Text field" is defined as 10, then value given for it in API cannot be "12345678901", since it has 11 characters.

  • Duplicates are checked for every insert record API call based on unique fields.

  • A maximum of 100 records can be inserted/updated per API call.

  • You must use only Field API names in the input. You can obtain the field API names from

    • Fields metadata API (the value for the key “api_name” for every field). (Or)

    • Setup > Developer Space > APIs > API Names > {{Module}}. Choose “Fields” from the “Filter By” drop-down.

  • The trigger input can be workflow, approval, or blueprint. If the trigger is not mentioned, the workflows, approvals and blueprints related to the API will get executed. Enter the trigger value as [] to not execute the workflows.

  • Records with Subform details can also be upserted to CRM using the Records API.

  • Refer Response Structure for more details about the JSON keys, values, and their descriptions. You can also use the sample response of each module as the input when you insert, update, or upsert a record in that corresponding module.

System-defined Duplicate Check Fields

  • Following are the default duplicate check fields for different modules.
    Leads - Email, Accounts - Account_Name, Contacts - Email, Deals - Deal_Name, Campaigns - Campaign_Name, Cases - Subject, Solutions - Solution_Title, Products - Product_Name, Vendors - Vendor_Name, PriceBooks - Price_Book_Name, Quotes - Subject, SalesOrders - Subject, PurchaseOrders - Subject, Invoices - Subject, CustomModules - Name

Sample Attributes

The following table gives you specific details about each field type in Zoho CRM and their limitations.
The JSON type and the data type of the field-types are extracted from fields meta data API.
JSON type - Represents the format in which the field should be passed in the request-body or will be received in the response.
Data type - Represents the type of data that can be stored in the corresponding field-type. It is mentioned below each Attribute.

 
AttributeJSON TypeLimitationsSample
Single Line
Text
StringAccepts up to 255 characters.
Accepts alphanumeric and special characters.
"Last_Name": "Mike O'Leary"
Multi Line
Textarea
StringSmall - accepts up to 2000 characters.
Large - accepts up to 32000 characters.
You will not be able to use this field to create custom views, reports or other filters.
Accepts alphanumeric and special characters.
"Multi_Line_1": "This is the first line \n Now for the second Line"
Email
Email
StringAccepts valid email IDs."Email_1": "p.boyle@zylker.com"
Phone
Phone
StringAccepts up to 30 characters. This limit may vary based on the value configured in 'Number of characters allowed' in the properties pop-up of the field, in UI.
Accepts only numeric characters and '+' (to add extensions).
The regex pattern in Zoho CRM to validate this field's value is "[0-9a-zA-Z!#;%\\*\\^\\(\\)=\\{\\}\\[\\]\\?`~_\\-\\.\\$@\\?\\,\\:\\'\\/\\!\\P{InBasicLatin}\\|\\\\\\s\\+]+"
"Phone_1": "9900000000"
Picklist
Picklist
StringYou can either pass an existing pick list value or add a new one.
The pick list value accepts all alphanumeric and special characters.
"Industry": "automobile"
Multi-Select Picklist
Multi-select Picklist
JSON arrayYou can either pass existing pick list values or add a new one.
The pick list value accepts all alphanumeric and special characters.
"Courses_Opted": [
"Analytics",
"Big data"
]
Date
Date in ISO 8601 format
StringAccepts date in yyyy-MM-dd format"Date_1": "2017-08-16"
Date/time
DateTime in ISO 8601 format
StringAccepts date and time in yyyy-MM-ddTHH:mm:ss±HH:mm ISO 8601 format"Date_Time": "2017-08-16T14:32:23+05:30"
Date_Time is in ISO8601 format and the time zone is the current user's time zone.
Number
Integer
IntegerAccepts numbers up to 9 digits. This limit may vary based on the value configured in 'Maximum digits allowed' in the properties pop-up of the field, in UI.
Accepts only numeric values.
"No_of_Employees": 350
Currency
Currency
DoubleBefore decimal point - accepts numbers up to 16 digits. This limit may vary based on the value configured in 'Maximum digits allowed' in the properties pop-up of the field, in UI.
After decimal point - accepts precision up to 9 digits. This limit may vary based on the value configured in 'Number of decimal places' in the properties pop-up of the field, in UI.
Accepts only numeric values.
"Annual_Revenue": 250000.90
Decimal
Double
DoubleBefore decimal point - accepts numbers up to 16 digits. This limit may vary based on the value configured in 'Maximum digits allowed' in the properties pop-up of the field, in UI.
After decimal point - accepts precision up to 9 digits. This limit may vary based on the value configured in 'Number of decimal places' in the properties pop-up of the field, in UI.
Accepts only numeric values.
"Decimal_1": 250000.50
Percent
Double
DoubleAccepts numbers up to 5 digits.
Accepts only numeric values.
"Percentage": 25
Long Integer
BigInt
StringAccepts numbers up to 18 digits. This limit may vary based on the value configured in 'Maximum digits allowed' in the properties pop-up of the field, in UI.
Accepts only numeric values.
"EAN_Code":"0012345600012"
Checkbox
Boolean
BooleanAccepts only Boolean values(true,false)."Email_Opt_Out": true
URL
Website
StringAccepts valid URLs.
The regex pattern in Zoho CRM to validate this field's value is "^(http:\\/\\/www.|https:\\/\\/www.|ftp:\\/\\/www.|www.|http:\\/\\/|https:\\/\\/|ftp:\\/\\/|){1}[^\\x00-\\x19\\x22-\\x27\\x2A-\\x2C\\x2E-\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B\\x7D-\\x7F]+(\\.[^\\x00-\\x19\\x22\\x24-\\x2C\\x2E-\\x2F\\x3C\\x3E\\x40\\x5B-\\x5E\\x60\\x7B\\x7D-\\x7F]+)+(\\/[^\\x00-\\x19\\x22\\x3C\\x3E\\x5E\\x7B\\x7D-\\x7D\\x7F]*)*$"
"URL": "https://www.zylker.com"
Lookup
Lookup
JSON objectAccepts unique ID of the record, which you can get through Get Records API."Lookup" : {
"id" : "425248000000104001"
}
User
User Lookup
JSON objectThis is a default look-up field to users in Zoho CRM."User":
{
"name":"Patricia Boyle",
"id":"4150868000000623001"
}

Sample Request

In the request, "@upsertlead.json" contains the sample input data.


				curl "https://www.zohoapis.com/crm/v2/Leads/upsert"
-H "Authorization: Zoho-oauthtoken 1000.8cb99dxxxxxxxxxxxxx9be93.9b8xxxxxxxxxxxxxxxf"
-d "@upsertlead.json"
-X POST			

Sample Input

In the input, "Email" is the default duplicate check field for the Leads module, and "Mobile" is the user-defined primary field.


				{
    "data": [
        {
            "Last_Name": "Lead_changed",
            "Email": "newcrmapi@zoho.com",
            "Company": "abc",
            "Lead_Status": "Contacted"
        },
        {
            "Last_Name": "New Lead",
            "First_Name": "CRM Lead",
            "Email": "newlead@zoho.com",
            "Lead_Status": "Attempted to Contact",
            "Mobile": "7685635434"
        }
    ],
    "duplicate_check_fields": [
        "Email",
        "Mobile"
    ],
    "trigger":[ "workflow"]
}			

Sample Response


				{
    "data": [
        {
            "code": "SUCCESS",
            "duplicate_field": "Email",
            "action": "update",
            "details": {
                "Modified_Time": "2019-05-07T11:39:53+05:30",
                "Modified_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                },
                "Created_Time": "2019-05-07T11:29:52+05:30",
                "id": "554023000000550011",
                "Created_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                }
            },
            "message": "record updated",
            "status": "success"
        },
        {
            "code": "SUCCESS",
            "duplicate_field": null,
            "action": "insert",
            "details": {
                "Modified_Time": "2019-05-07T11:39:53+05:30",
                "Modified_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                },
                "Created_Time": "2019-05-07T11:39:53+05:30",
                "id": "554023000000550024",
                "Created_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                }
            },
            "message": "record added",
            "status": "success"
        }
    ]
}			

Sample Request


				List records = new ArrayList<>();
ZCRMRecord record1 = new ZCRMRecord("Leads"); // module api name
record1.setFieldValue("Company", "abc");
record1.setFieldValue("Last_Name", "Lead_changed");
record1.setFieldValue("Email", "newcrmapi@zoho.com");
record1.setFieldValue("Lead_Status", "Contacted");
ZCRMRecord record2 = new ZCRMRecord("Leads"); // module api name
record2.setFieldValue("Company", "abc");
record2.setFieldValue("First_name", "CRM Lead");
record2.setFieldValue("Last_Name", "New Lead");
record2.setFieldValue("Email", "newlead@zoho.com");
record1.setFieldValue("Lead_Status", "Attempted to Contact");
records.add(record1);
records.add(record2);
ZCRMModule module = ZCRMModule.getInstance("Leads"); //module api name
BulkAPIResponse response = module.upsertRecords(records);
List<ZCRMRecord> upsertedRecords = (List<ZCRMRecord>) response.getData();
List<BulkAPIResponse.EntityResponse> entityResponses = response.getEntityResponses();// to check the status of the request
String rec1Status = entityResponses.get(0).getStatus();//check status of record1
String rec2Status = entityResponses.get(1).getStatus();//check status of record2			

Sample Response


				{
    "data": [
        {
            "code": "SUCCESS",
            "duplicate_field": "Email",
            "action": "update",
            "details": {
                "Modified_Time": "2019-05-07T11:39:53+05:30",
                "Modified_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                },
                "Created_Time": "2019-05-07T11:29:52+05:30",
                "id": "554023000000550011",
                "Created_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                }
            },
            "message": "record updated",
            "status": "success"
        },
        {
            "code": "SUCCESS",
            "duplicate_field": null,
            "action": "insert",
            "details": {
                "Modified_Time": "2019-05-07T11:39:53+05:30",
                "Modified_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                },
                "Created_Time": "2019-05-07T11:39:53+05:30",
                "id": "554023000000550024",
                "Created_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                }
            },
            "message": "record added",
            "status": "success"
        }
    ]
}			

Sample Request


				$zcrmModuleIns = ZCRMModule::getInstance("Leads");
$bulkAPIResponse=$zcrmModuleIns->upsertRecords($recordsArray); // $recordsArray - array of ZCRMRecord instances filled with required data for upsert.
$entityResponses = $bulkAPIResponse->getEntityResponses();
foreach($entityResponses as $entityResponse)
{
      if("success"==$entityResponse->getStatus())
      {
            echo "Status:".$entityResponse->getStatus();
            echo "Message:".$entityResponse->getMessage();
            echo "Code:".$entityResponse->getCode();
            $upsertData=$entityResponse->getUpsertDetails();
            echo "UPSERT_ACTION:".$upsertData[“action”];
            echo "UPSERT_DUPLICATE_FIELD:".$upsertData[“duplicate_field”];
            $createdRecordInstance=$entityResponse->getData();
            echo "EntityID:".$createdRecordInstance->getEntityId();
            echo "moduleAPIName:".$createdRecordInstance->getModuleAPIName();
            ….
      }
}			

Sample Response


				{
    "data": [
        {
            "code": "SUCCESS",
            "duplicate_field": "Email",
            "action": "update",
            "details": {
                "Modified_Time": "2019-05-07T11:39:53+05:30",
                "Modified_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                },
                "Created_Time": "2019-05-07T11:29:52+05:30",
                "id": "554023000000550011",
                "Created_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                }
            },
            "message": "record updated",
            "status": "success"
        },
        {
            "code": "SUCCESS",
            "duplicate_field": null,
            "action": "insert",
            "details": {
                "Modified_Time": "2019-05-07T11:39:53+05:30",
                "Modified_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                },
                "Created_Time": "2019-05-07T11:39:53+05:30",
                "id": "554023000000550024",
                "Created_By": {
                    "name": "Patricia Boyle",
                    "id": "554023000000235011"
                }
            },
            "message": "record added",
            "status": "success"
        }
    ]
}			

Sample Request


				def upsert_records(self):
        try:
            record_ins_list = list()
            for i in range(0, 2):
                record = ZCRMRecord.get_instance('Invoices')  # module API Name
                record.set_field_value('Subject', 'Invoice' + str(i))
                record.set_field_value('Account_Name', 'IIIT')
                user = ZCRMUser.get_instance(440872000000175001, 'Python Automation User1')
                record.set_field_value('Owner', user)
                line_item = ZCRMInventoryLineItem.get_instance(ZCRMRecord.get_instance("Products", 440872000000224005))
                line_item.discount = 10
                line_item.list_price = 8
                line_item.description = 'Product Description'
                line_item.quantity = 100
                line_item.tax_amount = 2.5
                taxIns = ZCRMTax.get_instance("Vat")
                taxIns.percentage = 5
                line_item.line_tax.append(taxIns)
                record.add_line_item(line_item)
                record_ins_list.append(record)
                record = ZCRMRecord.get_instance('Invoices', 440872000000248818)
                record.set_field_value('Subject', 'Invoice1.1')
                line_item = ZCRMInventoryLineItem.get_instance(ZCRMRecord.get_instance("Products", 440872000000224005))
                line_item.discount = 10
                line_item.list_price = 8
                line_item.description = 'Product Description'
                line_item.quantity = 100
                line_item.tax_amount = 2.5
                taxIns = ZCRMTax.get_instance("Vat")
                taxIns.percentage = 5
                line_item.line_tax.append(taxIns)
                record.add_line_item(line_item)
                record_ins_list.append(record)
                resp = ZCRMModule.get_instance('Invoices').upsert_records(record_ins_list)
                print(resp.status_code)
                entity_responses = resp.bulk_entity_response
                for entity_response in entity_responses:
                    print(entity_response.details)
                    print(entity_response.status)
                    print(entity_response.message)
                    print(entity_response.code)
                    print(entity_response.data.entity_id)
                    print(entity_response.data.created_by.id)
                    print(entity_response.data.created_time)
                    print(entity_response.data.modified_by.id)
                    print("\n\n")
        except ZCRMException as ex:
            print(ex.status_code)
            print(ex.error_message)
            print(ex.error_code)
            print(ex.error_details)
            print(ex.error_content)			

Sample Response


				{
    "data": [
       {
            "message": "record updated",
            "details": {
                "created_by": {
                    "id": "4108880000086001",
                    "name": "Patricia Boyle"
                },
                "id": "410888000000478065",
                "modified_by": {
                    "id": "4108880000086001",
                    "name": "Patricia Boyle"
                },
                "modified_time": "2016-04-28T17:59:21+05:30",
                "created_time": "2016-04-28T17:59:21+05:30"
            },
            "status": "success",
            "duplicate_field": "Subject",
            "action": "update",
            "code": "SUCCESS"
        },
       {
            "message": "record updated",
            "details": {
                "created_by": {
                    "id": "4108880000086001",
                    "name": "Patricia Boyle"
                },
                "id": "4108880000478066",
                "modified_by": {
                    "id": "4108880000086001",
                    "name": "Patricia Boyle"
                },
                "modified_time": "2016-04-28T17:59:21+05:30",
                "created_time": "2016-04-28T17:59:21+05:30"
            },
            "status": "success",
            "duplicate_field": "Email",
            "action": "update",
            "code": "SUCCESS"
        }
    ]
}			

Sample Request


				Syntax:
<response> = zoho.crm.upsert(<module>,<values>,<optional_data>,<[connection>]);
mandatory : module,dataMap

Sample Request:
resp = zoho.crm.upsert("Leads", {"Last_Name":"Patricia upsert UF2", "UF":"p.boyle@zylker.com", "Email":"d.grogan@zylker.com"}, {"duplicate_check_fields":["UF" , "Email"]});			

Sample Response


				{
    "data": [
       {
            "message": "record updated",
            "details": {
                "created_by": {
                    "id": "4108880000086001",
                    "name": "Patricia Boyle"
                },
                "id": "410888000000478065",
                "modified_by": {
                    "id": "4108880000086001",
                    "name": "Patricia Boyle"
                },
                "modified_time": "2016-04-28T17:59:21+05:30",
                "created_time": "2016-04-28T17:59:21+05:30"
            },
            "status": "success",
            "duplicate_field": "Email",
            "action": "update",
            "code": "SUCCESS"
        }
    ]
}			

Sample Request


				List<ZCRMRecord> records = new List<ZCRMRecord>();
ZCRMRecord record1 = new ZCRMRecord("Leads"); //module api name
record1.SetFieldValue("Company", "abc");
record1.SetFieldValue("Last_Name", "Lead_changed");
record1.SetFieldValue("Email", "newcrmapi@zoho.com");
record1.SetFieldValue("State", "Texas");
ZCRMRecord record2 = new ZCRMRecord("Leads"); //module api name
record2.SetFieldValue("Company", "abc");
record2.SetFieldValue("First_name", "CRM Lead");
record2.SetFieldValue("Last_Name", "New Lead");
record2.SetFieldValue("Email", "newlead@zoho.com");
record2.SetFieldValue("State", "Texas");
records.Add(record1);
records.Add(record2);
ZCRMModule moduleIns = ZCRMModule.GetInstance("Leads"); //module api name
BulkAPIResponse<ZCRMRecord> response = moduleIns.UpsertRecords(records); //records - list of ZCRMRecord instances filled with required data for upsert.
List<ZCRMRecord> upsertedRecords = response.BulkData; //upsertedRecords - list of ZCRMRecord instance
List<EntityResponse> entityResponses = response.BulkEntitiesResponse; //entityResponses - list of EntityResponses instance			

Sample Response


				{
  "data": [
    {
      "code": "SUCCESS",
      "duplicate_field": "Email",
      "action": "update",
      "details": {
        "Modified_Time": "2019-05-07T11:39:53+05:30",
        "Modified_By": {
          "name": "Patricia Boyle",
          "id": "554023000000235011"
        },
        "Created_Time": "2019-05-07T11:29:52+05:30",
        "id": "554023000000550011",
        "Created_By": {
          "name": "Patricia Boyle",
          "id": "554023000000235011"
        }
      },
      "message": "record updated",
      "status": "success"
    },
    {
      "code": "SUCCESS",
      "duplicate_field": null,
      "action": "insert",
      "details": {
        "Modified_Time": "2019-05-07T11:39:53+05:30",
        "Modified_By": {
          "name": "Patricia Boyle",
          "id": "554023000000235011"
        },
        "Created_Time": "2019-05-07T11:39:53+05:30",
        "id": "554023000000550024",
        "Created_By": {
          "name": "Patricia Boyle",
          "id": "554023000000235011"
        }
      },
      "message": "record added",
      "status": "success"
    }
  ]
}