Reference

Source code


<?xml version="1.0" encoding="utf-8"?>
<ApiConfig Name="Zoho CRM"
  EngineVersion="16"
  Version="8"
  Id="1C3FF995-9EE6-4C55-A654-37141622704B"
	Slug="zoho-crm-connector"
	Desc="Read and write Zoho CRM data effortlessly. Integrate, manage, and automate accounts, leads, contacts, and deals — almost no coding required."
	HelpLink="https://www.zoho.com/crm/developer/docs/api/"
	Logo="data:image/png;base64,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"
	>
  <VersionHistory>
    <Change Date="2024-06-02">Allow to choose API version</Change>
    <Change Date="2024-06-02">Allow select API version using connection level Option (Service URL must be changed to match API Version Parameter). Default Version is V2 and its almost 2 times faster than higher API version (e.g. V3+) but V2 may return less number of columns compared to new API versions (e.g. v3...v7+). API V2 makes less number of requests and returns more records per call (200 rows), on the other side V3+ has limits of max 50 fields in each Get Records API calls. To avoid this limitation in V3+ API we used /{module}?ids={150 ids} workaround but this is still slower compred to older API (v2) approach. Choose new API if you have a valid reason (e.g. you need additional new columns exposed in v3+) else stick with older version V2 (its default setting).</Change>
    <Change Date="2024-06-02">Updated sort order for select and lookup endpoints now they should match with field orders returned from get_module_fields</Change>
    <Change Date="2024-06-02">Updated cache mode for get_module_fields to UseRawCache</Change>
    <Change Date="2024-06-02">Updated datacenter list (Added CA, SA, JP and more)</Change>    
    <Change Date="2024-06-02" Type="Fix">Lookup fields are NULL and Lookup_Field_Id is not in the output (e.g. select Account_Name from Deals)</Change>
    <Change Date="2024-06-02">Document Lookup write examples (Insert, Update)</Change>    
    <Change Date="2023-04-25">Show non-approved records too when you query by id (e.g. SELECT * FROM Leads WHERE Id=1234)</Change>
    <Change Date="2023-04-25">Added Id column support for DELETE (e.g. DELETE FROM Account Where Id=123)</Change>
    <Change Date="2023-04-25">Added api_name column in the output for UPSERT so when error occurs you know which field causing it</Change>
    <Change Date="2022-04-27">Added retry logic for limit reached error (status code 429)</Change>
    <Change Date="2022-01-31">Added new endpoints for Tags read/write (get_tags, get_tag_record_count, post_tags)</Change>
    <Change Date="2022-01-31">Added support for Lookup operation in SELECT, and WHERE clause for DELETE and UPDATE</Change>
    <Change Date="2021-11-02">Fixed bulk delete operation issue</Change>
    <Change Date="2021-03-15">Renamed If-Modified-Since option to ModifiedSince</Change>
    <Change Date="2021-01-15" Type="Fix">If-Modified-Since option is not working - Read data modified after some datetime</Change>
    <Change Date="2020-12-01">Initial version</Change>
  </VersionHistory>

  <ServiceUrls>
    <ServiceUrl Name="United States (US) Datacenter" Url="https://www.zohoapis.com/crm/[$Version$]"/>
    <ServiceUrl Name="Europe (EU) Datacenter" Url="https://www.zohoapis.eu/crm/[$Version$]"/>
    <ServiceUrl Name="Australia (AU) Datacenter" Url="https://www.zohoapis.com.au/crm/[$Version$]"/>
    <ServiceUrl Name="India (IN) Domain" Url="https://www.zohoapis.in/crm/[$Version$]"/>
	<ServiceUrl Name="Japan (JP) Datacenter" Url="https://www.zohoapis.jp/crm/[$Version$]"/>
    <ServiceUrl Name="China (CN) Datacenter" Url="https://www.zohoapis.com.cn/crm/[$Version$]"/>
	<ServiceUrl Name="Canada (CA) Datacenter" Url="https://www.zohoapis.ca/crm/[$Version$]"/>
	<ServiceUrl Name="Saudi Arabia (SA) Datacenter" Url="https://www.zohoapis.sa/crm/[$Version$]"/>
  </ServiceUrls>
 

  <!-- https://www.zoho.com/crm/developer/docs/api/access-refresh.html -->
  <Auths>
    <Auth Type="OAuth" Desc="OAuth Connection for Zoho CRM API" HelpLink="https://www.zoho.com/crm/developer/docs/api/register-client.html"
          ConnStr="Provider=Custom;OAuthVersion=OAuth2;ScopeSeparator={space};ReturnUrl=[$RedirectUrl$];ExtraAttributesForAuthRequest=access_type=offline&amp;prompt=consent;AuthUrl=[$AccountUrl$]/oauth/v2/auth;TokenUrl=[$AccountUrl$]/oauth/v2/token;ClientId=[$ClientId$];ClientSecret=[$ClientSecret$];Scope=[$Permissions$];ExpiresInAttribute=expires_in_sec;" TestEndPoint="get_modules">
      <Params>
        <Param Name="ClientId" />
        <Param Name="ClientSecret" Secret="True" />
        <Param Name="Permissions" Value="ZohoCRM.settings.all ZohoCRM.modules.all ZohoCRM.coql.READ" Desc="To access Visists table you need add extra permissions and re-generate token (e.g. Append ZohoCRM.modules.visits.ALL OR try ZohoCRM.modules.visits.READ, ZohoCRM.modules.visits.DELETE to the value for this property)"/>
        <Param Name="AccountUrl" Value="https://accounts.zoho.com"
               Options="United States (US) Datacenter=https://accounts.zoho.com;
			   United Kingdom (UK) Datacenter=https://accounts.zoho.uk;
			   Europe (EU) Datacenter=https://accounts.zoho.eu;
			   Canada (CA) Datacenter=https://accounts.zohocloud.ca;
			   Australia (AU) Datacenter=https://accounts.zoho.au;
			   India (IN) Datacenter=https://accounts.zoho.in;
			   Japan (JP) Datacenter=https://accounts.zoho.jp;			   
			   Saudi Arabia (SA) Datacenter=https://accounts.zoho.sa;			   
			   China (CN) Datacenter=https://accounts.zoho.com.cn;"   

			   HelpLink="https://www.zoho.com/accounts/protocol/oauth/multi-dc.html"
			   />
        <Param Name="RedirectUrl" Value="https://zappysys.com/oauth" Desc="This is the redirect URL you entered when you created app in Zoho Portal. URL must match exactly including trailing slash" />
		<Param Name="Version" Label="API Version" Value="v2" Options="v2 (Fast)=v2;v3=v3;v4=v4;v5=v5;v6=v6;v7=v7;Enter Your Custom Version=type-version-here" Desc="Zoho CRM API version. After v2 there are some changes the way fields returned so choose API version carefully. V2 is faster compred to newer version." />
		
        <!--below not exposed as root level property in HTTP Connection so use as placeholder-->
        <Param Name="RetryMode" Value="RetryWhenStatusCodeMatch" Options="None;RetryAny;RetryWhenStatusCodeMatch;" Hidden="True"  HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/status-codes.html" />
        <Param Name="RetryStatusCodeList" Value="429" Hidden="True" />
        <Param Name="RetryCountMax" Value="5" Hidden="True" />
        <Param Name="RetryMultiplyWaitTime" Value="True" Hidden="True" />
	
      </Params>
      <Notes>
        <![CDATA[To register custom App, perform the following steps (Detailed steps found in the help link at the end)
<ol>
  <li>Go to <a target="_blank" href="https://api-console.zoho.com/">Zoho API Console</a>
  <li>Click <b>Add Client</b> link
  <li>Select <b>Server-based Applications</b> option
  <li>Enter desired client name (Display purpose only)</b>
  <li>Enter some URL for Company homepage</b>
  <li>For Authorized Redirect URI enter https://zappysys.com/oauth (Or enter your own but we recommend using ZappySys one if possible). This URL must match on Zoho Connector UI.
  <li>Click <b>CREATE</b>.
  <li>Copy Client ID and Secret and paste on Zoho Connector UI.
</ol>
]]>
      </Notes>
    </Auth>
  </Auths>

  <Template>
    <!-- When name not specified in EndPoints node .. its considered as base for all other template -->
    <EndPoint Name="Pagination">
      <Params>
        <Param Name="WaitTimeMs" Label="Wait Time After Request (Ms)" Type="Property" Value="0" />
        <Param Name="Filter" Type="Property" Desc="Filter for JSON" Value="$.data[*]" />
        <Param Name="NextUrlEndIndicator" Type="Property" Value="false" />
        <Param Name="StopIndicatorAttributeOrExpr" Type="Property" Value="$.info.more_records" />
        <Param Name="PagingMode" Type="Property" Value="ByUrlParameter" />
        <Param Name="PagingByUrlAttributeName" Type="Property" Value="page" />
        <Param Name="PagingByUrlEndStrategy" Type="Property" Value="DetectBasedOnMultipleRules" />
		
        <Param Name="PagingEndRules" Type="Property" 
				Value="&lt;ArrayOfPagingEndRule&gt;&lt;PagingEndRule&gt;&lt;Mode&gt;DetectBasedOnResponseStatusCode&lt;/Mode&gt;&lt;StatusCode&gt;204&lt;/StatusCode&gt;&lt;/PagingEndRule&gt;&lt;PagingEndRule&gt;&lt;Mode&gt;DetectBasedOnResponseStatusCode&lt;/Mode&gt;&lt;StatusCode&gt;304&lt;/StatusCode&gt;&lt;/PagingEndRule&gt;&lt;PagingEndRule&gt;&lt;Mode&gt;DetectBasedOnResponseStatusCode&lt;/Mode&gt;&lt;Mode&gt;DetectBasedOnRecordCount&lt;/Mode&gt;&lt;/PagingEndRule&gt;&lt;/ArrayOfPagingEndRule&gt;" />

		<Param Name="PageSize" Key="per_page" Value="" Options=";200;100;50;10" Type="Query" Hidden="True"/>

	  </Params>
    </EndPoint>
    <EndPoint Name="ModulePagination" Template="Pagination">
      <Params>
        <Param Name="approved" Type="Query" Label="Return Approved Records" Desc="To get the list of approved records. Default value is true." Options=";true;false;both"  />
        <Param Name="converted" Type="Query" Label="Return Converted Records" Desc="To retrieve the list of converted records. Default value is false." Options=";true;false;both"  />

      </Params>

      <OutputColumns>
        <!--Column Name="id" Label="Id" DataType="DT_WSTR" Length="25" /-->
        <Column Name="-Dynamic-" Expand="True" DataEndPoint="get_module_fields" DataEndPointParameters="module=[$parent.api_name$];Filter=$.fields[?(@json_type!='jsonobject')];"
                ColumnInfoMap="Name=api_name;DataType=data_type;Length=length;Raw=json_type"
                RawInfoMap="jsonobject;jsonarray"
                DataTypeMap="DT_BOOL=boolean;DT_I8=bigint;DT_I4=integer;DT_WSTR=profileimage,ownerlookup,text,picklist,phone,website,lookup;DT_DBTIMESTAMP=datetime,date;DT_R8=currency,double;DT_NTEXT=textarea"
                Order="1"
				/>

        <Column Name="[$parent.api_name$].name" Label="[$parent.api_name$]" Expand="True" DataEndPoint="get_module_fields" DataEndPointParameters="module=[$parent.api_name$];Filter=$.fields[?(@json_type=='jsonobject')];"
                ColumnInfoMap="Name=api_name;DataType=data_type;Length=length;Raw=json_type"
                RawInfoMap="jsonobject;jsonarray"
                DataTypeMap="DT_BOOL=boolean;DT_I8=bigint;DT_I4=integer;DT_WSTR=profileimage,ownerlookup,text,picklist,phone,website,lookup;DT_DBTIMESTAMP=datetime,date;DT_R8=currency,double;DT_NTEXT=textarea"
                Order="501"/>
        <Column Name="[$parent.api_name$].id" Label="[$parent.api_name$]_Id" Expand="True" DataEndPoint="get_module_fields" DataEndPointParameters="module=[$parent.api_name$];Filter=$.fields[?(@json_type=='jsonobject')];"
                ColumnInfoMap="Name=api_name;DataType=data_type;Length=length;Raw=json_type"
                RawInfoMap="jsonobject;jsonarray"
                DataTypeMap="DT_BOOL=boolean;DT_I8=bigint;DT_I4=integer;DT_WSTR=profileimage,ownerlookup,text,picklist,phone,website,lookup;DT_DBTIMESTAMP=datetime,date;DT_R8=currency,double;DT_NTEXT=textarea"
                Order="502"/>


        <Column Name="Created_By.id" Label="Created_By_Id" DataType="DT_WSTR" Length="25" Order="1001"/>
        <Column Name="Created_By.email" Label="Created_By_Email" DataType="DT_WSTR" Length="255" Order="1002"/>
        <Column Name="Created_By.name" Label="Created_By_Name" DataType="DT_WSTR" Length="255" Order="1003"/>

        <Column Name="Modified_By.id" Label="Modified_By_Id" DataType="DT_WSTR" Length="25" Order="1004"/>
        <Column Name="Modified_By.email" Label="Modified_By_Email" DataType="DT_WSTR" Length="255" Order="1005"/>
        <Column Name="Modified_By.name" Label="Modified_By_Name" DataType="DT_WSTR" Length="255" Order="1006"/>

        <Column Name="Owner.id" Label="Owner_Id" DataType="DT_WSTR" Length="25" Order="1007"/>
        <Column Name="Owner.email" Label="Owner_Email" DataType="DT_WSTR" Length="255" Order="1008"/>
        <Column Name="Owner.name" Label="Owner_Name" DataType="DT_WSTR" Length="255" Order="1009"/>



        <Column Name="$approval_state" DataType="DT_WSTR" Length="20" Order="1010"/>
        <Column Name="$approved" DataType="DT_BOOL" Order="1011"/>
        <Column Name="$state" DataType="DT_WSTR" Length="50" Order="1012"/>
      </OutputColumns>
    </EndPoint>

    <EndPoint Name="CRUD" Template=".">
      <OutputColumns>
        <Column Name="details.id" Label="id" DataType="DT_WSTR" Length="255" Order="-5" />
        <Column Name="code" DataType="DT_WSTR" Length="255" Order="-4" />
        <Column Name="message" DataType="DT_WSTR" Length="1000" Order="-3" />
        <Column Name="status" DataType="DT_WSTR" Length="255" Order="-2" />
      </OutputColumns>
    </EndPoint>

    <EndPoint Name="NoPagination" Template=".">

    </EndPoint>

  </Template>

  <EndPoints>

    <EndPoint Method="POST" Name="get_module_data_coql" Template="NoPagination"
      Label="Read Data (Query Mode - Max 200 Rows Only)"
      Url="/coql" Body="{&quot;select_query&quot;: &quot;[$sql_query$]&quot;}" Filter="$.data[*]">
      <Params>
        <Param Editor="MultiLine" Name="sql_query" Desc="Your SQL query for CRM (i.e. COQL (CRM Object Query Language)). Limtation - You can fetch maximum 200 rows using COQL Query. To read all rows use Table mode. (refer to help link to learn more about COQL)"
               HelpLink="https://zappysys.com/links?url=https://www.zoho.com/crm/developer/docs/api/COQL-Overview.html"
Value="select Last_Name, First_Name, Full_Name from Contacts where Last_Name not like 'Boyle' limit 200" Functions="JSONENCODE;TRIM"/>

      </Params>
    </EndPoint>

    <EndPoint Name="get_modules" Label="List Modules" Url="/settings/modules" Template="NoPagination" Cached="True" CachedTtl="60" HelpLink="https://www.zoho.com/crm/developer/docs/api/modules-api.html">
      <Params>
        <Param Name="Filter" Type="Property" Desc="Filter for JSON" Value="$.modules[*]"
               Options="All Modules=$.modules[*];Modules With API Support=$.modules[?(@api_supported==true)];Modules Without API Support=$.modules[?(@api_supported==false)]" />
      </Params>
    </EndPoint>

    <EndPoint Name="get_territories" Label="List Territories" Url="/settings/territories" Filter="$.territories[*]" Template="NoPagination" Cached="True" CachedTtl="60" HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/territories.html">
    </EndPoint>

    <EndPoint Name="get_module_settings" Label="List Module Settings" Url="/settings/modules/[$module$]" Cached="True" CachedTtl="20" Desc="To get the metadata for a specific module. Specify the API name of the module, such as Leads, Accounts or Deals in your API request."
              Template="NoPagination" HelpLink="https://www.zoho.com/crm/developer/docs/api/modules-api.html">
      <Params>
        <Param Name="Filter" Type="Property" Desc="Filter for JSON" Value="$.modules[*]" Options="All Modules=$.modules[*];Module Profiles=$.modules[*].profiles[*];" />
        <Param Name="module" Required="True" Type="Query" Desc="Module name for which you like to get settings" Value=""
                       OptionsEndPoint="get_modules" OptionsEndPointValueColumn="api_name" OptionsEndPointLabelColumn="module_name"
                       Options="Accounts;Activities;Calls;Campaigns;Cases;Contacts;Deals;Events;Invoices;Leads;Price_Books;Products;Purchase_Orders;Quotes;Sales_Orders;Solutions;Tasks;Vendors;Your_Custom_Module_Name;"
               />
      </Params>
    </EndPoint>

    <EndPoint Name="get_tags" Group="Tags" Label="List Tags" Url="/settings/tags?per_page=2000" Cached="True" CachedTtl="20"
              Desc="List tags for module."
              Filter="$.tags[*]"
              Template="NoPagination" HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/get-tag-list.html"
      >
      <Params>
        <Param Name="module" Required="True" Type="Query" Desc="Module name for which you like to get settings" Value=""
                       OptionsEndPoint="get_modules" OptionsEndPointValueColumn="api_name" OptionsEndPointLabelColumn="module_name"
                       Options="Accounts;Activities;Calls;Campaigns;Cases;Contacts;Deals;Events;Invoices;Leads;Price_Books;Products;Purchase_Orders;Quotes;Sales_Orders;Solutions;Tasks;Vendors;Your_Custom_Module_Name;"
               />
      </Params>
      <OutputColumns>
        <Column Name="id" Label="Id" DataType="DT_WSTR" Length="25" />
        <Column Name="name" Label="Name" DataType="DT_WSTR" Length="255" />
        <Column Name="created_by.id" Label="Created_By_Id" DataType="DT_WSTR" Length="25" />
        <Column Name="created_by.name" Label="Created_By_Name" DataType="DT_WSTR" Length="255" />


        <Column Name="created_time" Label="Created_Time" DataType="DT_DBTIMESTAMP" />
        <Column Name="modified_time" Label="Modified_Time" DataType="DT_DBTIMESTAMP" />
      </OutputColumns>
    </EndPoint>

    <EndPoint Name="get_tag_record_count" Group="Tags" Label="Gets record count for specific tag for module" 
              Url="/settings/tags/[$tag_id$]/actions/records_count"
              Desc="Add tags for specified module and specified record id(s)."
              Template="NoPagination" HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/add-tags.html"
      >
      <Params>
        <Param Name="module" Type="Query" Required="True" Desc="Module name for which you like to get settings"
                       OptionsEndPoint="get_modules" OptionsEndPointValueColumn="api_name" OptionsEndPointLabelColumn="module_name"
                       Options="Accounts;Activities;Calls;Campaigns;Cases;Contacts;Deals;Events;Invoices;Leads;Price_Books;Products;Purchase_Orders;Quotes;Sales_Orders;Solutions;Tasks;Vendors;Your_Custom_Module_Name;"
               />
        <Param Name="tag_id" Required="True" Label="Tag Id" Desc="Use List Tags to findout Id for tag you like to query"
        OptionsEndPoint="get_module_tags" OptionsEndPointValueColumn="Id" OptionsEndPointLabelColumn="Name" OptionsEndPointParameters="module=[$module$]"        
      />
      </Params>
      <OutputColumns>
        <Column Name="count" Label="Count" DataType="DT_I8" />
      </OutputColumns>
    </EndPoint>

    <EndPoint Name="post_tags" Group="Tags" Label="Add / Update Tags for records" Url="[$module$]/actions/add_tags"
              Desc="Add tags for specified module and specified record id(s)."
              Filter="$.data[*]"
              Method="POST"
              MultiSelectSeparator=","
              Template="CRUD" HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/add-tags.html"
      >
      <Params>
        <Param Name="module" Required="True" Desc="Module name for which you like to get settings" Value=""
                       OptionsEndPoint="get_modules" OptionsEndPointValueColumn="api_name" OptionsEndPointLabelColumn="module_name"
                       Options="Accounts;Activities;Calls;Campaigns;Cases;Contacts;Deals;Events;Invoices;Leads;Price_Books;Products;Purchase_Orders;Quotes;Sales_Orders;Solutions;Tasks;Vendors;Your_Custom_Module_Name;"
               />
        <Param Name="ids" Type="Query" Required="True" Label="Record Id(s) (comma seperated list)" Desc="List of Record Id(s) you like to update" />
        <Param Name="tag_names" Type="Query" Required="True" Label="Tag Id" Desc="List of Tag(s) you like to add"
          MultiSelect="True" OptionsEndPoint="get_module_tags" OptionsEndPointValueColumn="Name" OptionsEndPointLabelColumn="Name" OptionsEndPointParameters="module=[$module$]" />      
        <Param Name="over_write" Label="Overwrite" Type="Query" Desc="Set this to overwrite exising tags for the record(s)" Options=";true;false"/>
      </Params>
      <OutputColumns>
        <Column Name="details.tags" Label="tags" DataType="DT_WSTR" Length="1000" Raw="True"/>
      </OutputColumns>
    </EndPoint>

    <EndPoint Name="get_module_fields" Label="List Module Fields" Url="/settings/fields" Template="NoPagination"
          Cached="True" CachedTtl="60" UseRawCache="True"
          Desc="To get the field meta data for the specified module. The fields displayed are from all layouts for the module and the response does not contain layout-specific fields like mandatory fields or picklist values.">
      <Params>
        <Param Name="module" Required="True" Type="Query" Desc="Module name for which you like to get all fields" Value=""
               OptionsEndPoint="get_modules" OptionsEndPointValueColumn="api_name" OptionsEndPointLabelColumn="module_name"
               Options="Accounts;Activities;Calls;Campaigns;Cases;Contacts;Deals;Events;Invoices;Leads;Price_Books;Products;Purchase_Orders;Quotes;Sales_Orders;Solutions;Tasks;Vendors;Your_Custom_Module_Name;"
               />
        <Param Name="Filter" Type="Property" Desc="Filter for JSON" Value="$.fields[*]"
               Options="All Fields=$.fields[*];Custom Fields=$.fields[?(@custom_field==true)];System defined fields=$.fields[?(@custom_field==false)];Fields which are not readonly=$.fields[?(@read_only==false)];Readonly fields=$.fields[?(@read_only==true)]" />
      </Params>
    </EndPoint>

    <EndPoint Name="get_module_views" Label="List Views" Url="/settings/custom_views" Template="NoPagination" Cached="True" CachedTtl="60" >
      <Params>
        <Param Name="module" Required="True" Type="Query" Desc="Module name for which you like to get all views" Value=""
               OptionsEndPoint="get_modules" OptionsEndPointValueColumn="api_name" OptionsEndPointLabelColumn="module_name"
               />
        <Param Name="Filter" Type="Property" Desc="Filter for JSON" Value="$.custom_views[*]" Options="All Views=$.custom_views[*];System defined views only=$.custom_views[?(@system_defined==true)];User defined views only=$.custom_views[?(@system_defined==false)]" />
      </Params>
    </EndPoint>

    <EndPoint Name="get_[$parent.api_name$]" Label="Read [$parent.module_name$]" Group="[$parent.api_name$]" 
		Expand="True" Template="ModulePagination" DataEndPoint="get_modules"
              ResponseFormat="Json" Url="[$parent.api_name$]"
              HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/get-records.html"
			  Desc="This endpoint reads records using bulk approach. Default API Version is V2 (set connection level) and its almost 2 times faster than higher API version (e.g. V3+) but V2 may return less number of columns compared to new API versions (e.g. v3...v7+). API V2 makes less number of requests and returns more records per call (200 rows), on the other side V3+ has limits of max 50 fields in each Get Records API calls. To avoid this limitation in V3+ API we used /{module}?ids={150 ids} workaround but this is still slower compred to older API (v2) approach. Choose new API if you have a valid reason (e.g. you need additional new columns exposed in v3+) else stick with older version V2 (its default setting)"
			  >
      <Params>
		<Param Name="Module" Value="[$parent.api_name$]" Hidden="True" PushToChildEndPoint="True"/>
        <Param Name="If-Modified-Since" Type="Header"
               Label="Fetch records modified after (local time format: yyyy-MM-ddTHH:mm:ss)" Desc="Supply this DateTime (Local Time in ISO 8601 format) - To get the list of recently modified records after this datetime."
               Value="1900-12-31T00:00:00" Functions="FUN_TO_UTC_DATE" Editor="DateTime"/>

        <Param Name="cvid" Type="Query" Label="Custom View ID" Desc="To get the list of records based on custom views."
            OptionsEndPoint="get_module_views" OptionEndPointParameters="module=[$parent.api_name$];"
            OptionsEndPointValueColumn="id" OptionsEndPointLabelColumn="display_value" />

		<Param Name="DisableChildEndPoint" Type="Property" PropertyScope="EndPoint" Value="True" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~|True|~|False,FUN_IF&gt;&gt;" />
		
		<Param Name="FieldsValue" Type="Property" PropertyScope="Parameter" Key="fields.Value" 
			Value="id" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~||~|id,FUN_IF&gt;&gt;" />
	
        <Param Name="fields" Label="Fields (Only for V2 API)" Type="Query" Desc="To retrieve specific field values. Kepp blank to get all fields."
            OptionsEndPoint="get_module_fields" OptionEndPointParameters="module=[$parent.api_name$];"
            OptionsEndPointValueColumn="api_name" 
			MultiSelect="True" 
			MultiSelectSeparator="," 
			MultiSelectAllOnBlank="False"
			MultiSelectLimit="0"
			ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~|{$value$}|~|id,FUN_IF&gt;&gt;"
			/>

        <Param Name="sort_by" Type="Query" Desc="Specify the field name based on which the records must be sorted."
            OptionsEndPoint="get_module_fields" OptionEndPointParameters="module=[$parent.api_name$];"
            OptionsEndPointValueColumn="api_name" />
        <Param Name="sort_order" Type="Query" Desc="To sort the list of records in either ascending or descending order." Options=";asc;desc" />
        <Param Name="territory_id" Type="Query" Desc="To get the list of records in a territory. Use get_territories endpoint to list Id and names."  />
        <Param Name="include_child" Type="Query" Desc="To include records from the child territories. Default is false."  Options=";true;false"/>
        <Param Name="converted" Type="Query" Desc="converted"  Options=";true;false;both"/>
      
	    <Param Name="PagingMode" Type="Property" Value="ByUrlParameter" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~|ByUrlParameter|~|ByResponseAttribute,FUN_IF&gt;&gt;"  />
		<Param Name="NextUrlAttributeOrExpr" Type="Property" Value="$.info.next_page_token" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~||~|{$value$},FUN_IF&gt;&gt;" />
		<Param Name="NextUrlSuffix" Type="Property" Value="page_token=&lt;%nextlink%&gt;" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~||~|{$value$},FUN_IF&gt;&gt;" />		      	  
	  
	  </Params>
      <OutputColumns>
        <Column Name="id" Label="Id" DataType="DT_WSTR" Length="25" Order="-2" />
      </OutputColumns>
	  
	  <EndPoint Name="child_search" RequestFormat="Csv" 
		Url="/[$Module$]?ids={$rows$}" 
		BatchSize="150" Filter="$.data[*]">
		<LayoutMap>
			<![CDATA[<?xml version="1.0" encoding="utf-8"?> 
			<settings> 
				<dataset id="root" readfrominput="True" /> 
				<map name="id" src="id" /> 
			</settings> 
			]]>
		</LayoutMap>
	   </EndPoint> 	  
    </EndPoint>
	
    <EndPoint Name="get_[$parent.api_name$]_fast" Label="Read [$parent.module_name$] (Use this for fewer than 50 Fields in v3+)" 
		Desc="Use this endpoint if you have fewer than 50 fields and you like to utilize newer APi e.g. V3+, If you calling older API V2 then you can use any endpoint (e.g. get_contacts or get_contacts_fast or Contacts table all yeilds same speed in V2)."
		Group="[$parent.api_name$]" 
		Expand="True" Template="ModulePagination" DataEndPoint="get_modules"
              ResponseFormat="Json" Url="[$parent.api_name$]"
              HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/get-records.html">
      <Params>
		<Param Name="Module" Value="[$parent.api_name$]" Hidden="True" PushToChildEndPoint="True"/>
        <Param Name="If-Modified-Since" Type="Header"
               Label="Fetch records modified after (local time format: yyyy-MM-ddTHH:mm:ss)" Desc="Supply this DateTime (Local Time in ISO 8601 format) - To get the list of recently modified records after this datetime."
               Value="1900-12-31T00:00:00" Functions="FUN_TO_UTC_DATE" Editor="DateTime"/>

        <Param Name="cvid" Type="Query" Label="Custom View ID" Desc="To get the list of records based on custom views."
            OptionsEndPoint="get_module_views" OptionEndPointParameters="module=[$parent.api_name$];"
            OptionsEndPointValueColumn="id" OptionsEndPointLabelColumn="display_value" />

		<Param Name="FieldsMultiSelectAllOnBlank" Type="Property" PropertyScope="Parameter" Value="False" Key="fields.MultiSelectAllOnBlank" 
			ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~|False|~|True,FUN_IF&gt;&gt;" />
			
		<Param Name="FieldsMultiSelectLimit" Type="Property" PropertyScope="Parameter" Value="0" Key="fields.MultiSelectLimit" 
			ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~|0|~|50,FUN_IF&gt;&gt;" />
		
		<ParamZZZ Name="FieldsValue" Type="Property" PropertyScope="Parameter" Key="fields.Value" 
			Value="id" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~||~|id,FUN_IF&gt;&gt;" />
	
        <Param Name="fields" Label="Fields (Only for V2 API)" Type="Query" Desc="To retrieve specific field values. Kepp blank to get all fields."
            OptionsEndPoint="get_module_fields" OptionEndPointParameters="module=[$parent.api_name$];"
            OptionsEndPointValueColumn="api_name" 
			MultiSelect="True" 
			MultiSelectSeparator="," 
			MultiSelectAllOnBlank="False"
			MultiSelectLimit="0"
			ValueTemplateZZZZ="&lt;&lt;[$Version$]|~|Eq|~|v2|~|{$value$}|~|id,FUN_IF&gt;&gt;"
			/>

        <Param Name="sort_by" Type="Query" Desc="Specify the field name based on which the records must be sorted."
            OptionsEndPoint="get_module_fields" OptionEndPointParameters="module=[$parent.api_name$];"
            OptionsEndPointValueColumn="api_name" />
        <Param Name="sort_order" Type="Query" Desc="To sort the list of records in either ascending or descending order." Options=";asc;desc" />
        <Param Name="territory_id" Type="Query" Desc="To get the list of records in a territory. Use get_territories endpoint to list Id and names."  />
        <Param Name="include_child" Type="Query" Desc="To include records from the child territories. Default is false."  Options=";true;false"/>
        <Param Name="converted" Type="Query" Desc="converted"  Options=";true;false;both"/>
      
	    <Param Name="PagingMode" Type="Property" Value="ByUrlParameter" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~|ByUrlParameter|~|ByResponseAttribute,FUN_IF&gt;&gt;"  />
		<Param Name="NextUrlAttributeOrExpr" Type="Property" Value="$.info.next_page_token" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~||~|{$value$},FUN_IF&gt;&gt;" />
		<Param Name="NextUrlSuffix" Type="Property" Value="page_token=&lt;%nextlink%&gt;" ValueTemplate="&lt;&lt;[$Version$]|~|Eq|~|v2|~||~|{$value$},FUN_IF&gt;&gt;" />		      	  
	  
	  </Params>
      <OutputColumns>
        <Column Name="id" Label="Id" DataType="DT_WSTR" Length="25" Order="-2" />
      </OutputColumns>
	   
    </EndPoint>	

    <EndPoint Name="search_[$parent.api_name$]" Group="[$parent.api_name$]" Expand="True" Template="ModulePagination" DataEndPoint="get_modules"
              ResponseFormat="Json" Label="Search [$parent.module_name$]" Url="[$parent.api_name$]/search" Desc="Search records by criteria or email or phone or word or id (specify only one parameter for search and keep other blank)"
              HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/search-records.html">
      <Params>
        <Param Name="criteria" Type="Query" 
               Label="Search By Criteria Expression" 
               Desc="You can supply upto 10 criterias. For more complex expression use Query API. Example: ((Last_Name:equals:Burns)and(First_Name:starts_with:Ma)). You can lookup row by ID like (id:equals:1458554000067017001). Here is Syntax for expression (({api_name}:{starts_with|equals|in|between|not_equal|greater_equal|less_equal}:{value})and/or({api_name}:{starts_with|equals|in|between|not_equal|greater_equal|less_equal}:{value})) " 
               Options="None=;Example of Equal=(id:equal:11223344);
               Example NOT EQUAL=(id:not_equal:11223344);
               Example OR (multiple conditions)=(id:equal:1111111)or(id:equal:222222222);
               Example IN=(id:in:1111111,222222222,333333333);
               Example START_WITH=(Last_Name:starts_with:pat);
               Example BETWEEN=(Created_Time:between:2024-02-01T18:52:56+00:00,2024-02-20T18:52:56+00:00)"
        />
        <Param Name="email" Type="Query" Label="Search By Email"  />
        <Param Name="phone" Type="Query" Label="Search By Phone"   />
        <Param Name="word" Type="Query" Label="Search By any Word" />
        <Param Name="id" Type="Query" Label="Search By Id" Key="criteria" ValueTemplate="id:equals:{$value$}" IsKey="True"/>
        <Param Name="converted" Type="Query" Options=";true;false;both" Label="Include only converted records" />
        <Param Name="approved" Type="Query" Options=";true;false;both" Value="both" Label="Include approved records" />
      </Params>
      <OutputColumns>
        <Column Name="id" Label="Id" DataType="DT_WSTR" Length="25" Order="-2" />
      </OutputColumns>
    </EndPoint>

    <EndPoint Name="delete_[$parent.api_name$]" Group="[$parent.api_name$]" Expand="True" Template="CRUD" DataEndPoint="get_modules"
              RequestFormat="Csv" ResponseFormat="Json" Label="Delete [$parent.module_name$]" Url="[$parent.api_name$]?ids=[$id$]" Method="DELETE"
              HelpLink="https://www.zoho.com/crm/developer/docs/api/v2/delete-records.html" Filter="$.data[*]" BatchSize="100">
      <Params>
        <Param Name="id" Label="Record ID(s) - Use Comma for multiple (e.g. 111,222)" IsKey="True" Required="True" Functions="{$rows$}"/>
        <Param Name="wf_trigger" Type="Query" Label="Fire Wordflow Trigger" Options=";true;false"/>
      </Params>

      <InputColumns>
        <Column Name="id" MapToParam="True" DataType="DT_WSTR" Length="50" Key="True"/>
      </InputColumns>

    </EndPoint>

    <EndPoint Name="post_[$parent.api_name$]" Group="[$parent.api_name$]" Expand="True" Template="CRUD" DataEndPoint="get_modules"
              Label="Insert [$parent.module_name$]" Url="[$parent.api_name$]" Method="POST"
      Filter="$.data[*]" BatchSize="100"  ContentType="application/json">

      <Body>
        <![CDATA[{
  "data": {$rows$},
  "trigger": [[$Triggers$]]
}]]>
      </Body>
      <Params>
        <Param Name="Triggers" Value="&quot;approval&quot;,&quot;workflow&quot;,&quot;blueprint&quot;"/>
      </Params>
      <OutputColumns>
        <Column Name="details.expected_data_type" Label="expected_data_type" DataType="DT_WSTR" Length="255" />
        <Column Name="details.api_name" Label="api_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_Time" Label="created_time" DataType="DT_DBTIMESTAMP" />
        <Column Name="details.Modified_Time" Label="modified_time" DataType="DT_DBTIMESTAMP" />
        <Column Name="details.Modified_By.name" Label="modified_by_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Modified_By.id" Label="modified_by_id" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_By.name" Label="created_by_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_By.id" Label="created_by_id" DataType="DT_WSTR" Length="255" />
      </OutputColumns>

      <InputColumns>
        <Column Name="-Dynamic-" Expand="True" DataEndPoint="get_module_fields" DataEndPointParameters="module=[$parent.api_name$];Filter=$.fields[?(@read_only==false)];"
                ColumnInfoMap="Name=api_name;DataType=data_type;Length=length;Raw=json_type"
                RawInfoMap="jsonobject;jsonarray"
                DataTypeMap="DT_BOOL=boolean;DT_I8=bigint;DT_I4=integer;DT_WSTR=profileimage,ownerlookup,text,picklist,phone,website,lookup;DT_DBTIMESTAMP=datetime,date;DT_R8=currency,double;DT_NTEXT=textarea"
                />
      </InputColumns>
    </EndPoint>

    <EndPoint Name="put_[$parent.api_name$]" Group="[$parent.api_name$]" Expand="True" Template="CRUD" DataEndPoint="get_modules"
               Label="Update [$parent.module_name$]" Url="[$parent.api_name$]" Method="PUT"
       Filter="$.data[*]" BatchSize="100"  ContentType="application/json">

      <Body>
        <![CDATA[{
  "data": {$rows$},
  "trigger": [[$Triggers$]]
}]]>
      </Body>
      <Params>
        <Param Name="Triggers" Value="&quot;approval&quot;,&quot;workflow&quot;,&quot;blueprint&quot;"/>
      </Params>
      <OutputColumns>
        <Column Name="details.expected_data_type" Label="expected_data_type" DataType="DT_WSTR" Length="255" />
        <Column Name="details.api_name" Label="api_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_Time" Label="created_time" DataType="DT_DBTIMESTAMP" />
        <Column Name="details.Modified_Time" Label="modified_time" DataType="DT_DBTIMESTAMP" />
        <Column Name="details.Modified_By.name" Label="modified_by_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Modified_By.id" Label="modified_by_id" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_By.name" Label="created_by_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_By.id" Label="created_by_id" DataType="DT_WSTR" Length="255" />
      </OutputColumns>

      <InputColumns>
        <Column Name="id" DataType="DT_WSTR" Length="25" Key="True" />
        <Column Name="-Dynamic-" Expand="True" DataEndPoint="get_module_fields" DataEndPointParameters="module=[$parent.api_name$];Filter=$.fields[?(@read_only==false)];"
                ColumnInfoMap="Name=api_name;DataType=data_type;Length=length;Raw=json_type"
                RawInfoMap="jsonobject;jsonarray"
                DataTypeMap="DT_BOOL=boolean;DT_I8=bigint;DT_I4=integer;DT_WSTR=profileimage,ownerlookup,text,picklist,phone,website,lookup;DT_DBTIMESTAMP=datetime,date;DT_R8=currency,double;DT_NTEXT=textarea"
                />
      </InputColumns>
    </EndPoint>

    <EndPoint Name="upsert_[$parent.api_name$]" Group="[$parent.api_name$]" Expand="True" Template="CRUD" DataEndPoint="get_modules"
               Label="Upsert [$parent.module_name$] (Update or Insert)" Url="[$parent.api_name$]/upsert" Method="POST"
       Filter="$.data[*]" BatchSize="100" ContentType="application/json">

      <Body>
        <![CDATA[{
  "data": {$rows$},
  "trigger": [[$Triggers$]],
  "duplicate_check_fields": [[$Duplicate_Check_Fields$]]
}]]>
      </Body>
      <Params>
        <Param Name="Triggers" Value="&quot;approval&quot;,&quot;workflow&quot;,&quot;blueprint&quot;"/>
        <Param Name="Duplicate_Check_Fields" Value="Email" MultiSelect="True" MultiSelectSeparator="," MultiSelectTemplate="&quot;{@value}&quot;" Options="By Email=Email;By Phone=Phone;By Mobile=Mobile"/>

      </Params>
      <OutputColumns>
        <Column Name="duplicate_field" DataType="DT_WSTR" Length="255" />
        <Column Name="details.expected_data_type" Label="expected_data_type" DataType="DT_WSTR" Length="255" />
        <Column Name="details.api_name" Label="api_name" DataType="DT_WSTR" Length="255" />		
        <Column Name="details.Modified_Time" Label="modified_time" DataType="DT_DBTIMESTAMP" />
        <Column Name="details.Modified_By.name" Label="modified_by_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Modified_By.id" Label="modified_by_id" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_Time" Label="created_time" DataType="DT_DBTIMESTAMP" />
        <Column Name="details.Created_By.name" Label="created_by_name" DataType="DT_WSTR" Length="255" />
        <Column Name="details.Created_By.id" Label="created_by_id" DataType="DT_WSTR" Length="255" />
      </OutputColumns>

      <InputColumns>
        <Column Name="-Dynamic-" Expand="True" DataEndPoint="get_module_fields" DataEndPointParameters="module=[$parent.api_name$];Filter=$.fields[?(@read_only==false)];"
                ColumnInfoMap="Name=api_name;DataType=data_type;Length=length;Raw=json_type"
                RawInfoMap="jsonobject;jsonarray"
                DataTypeMap="DT_BOOL=boolean;DT_I8=bigint;DT_I4=integer;DT_WSTR=profileimage,ownerlookup,text,picklist,phone,website,lookup;DT_DBTIMESTAMP=datetime,date;DT_R8=currency,double;DT_NTEXT=textarea"
                />
      </InputColumns>
    </EndPoint>

  </EndPoints>

  <Tables>
    <Table Name="[$parent.api_name$]" Expand="True" DataEndPoint="get_modules"
      SelectEndPoint="get_[$parent.api_name$]"
      LookupEndPoint="search_[$parent.api_name$]"
      InsertEndPoint="post_[$parent.api_name$]"
      UpdateEndPoint="put_[$parent.api_name$]"
      UpsertEndPoint="upsert_[$parent.api_name$]"
      DeleteEndPoint="delete_[$parent.api_name$]" >
    </Table>
  </Tables>
  <Examples>
    <Example Group="ODBC" Slug="read-accounts" Label="Read accounts">
      <Desc><![CDATA[<p>Reads all records from the <code>Accounts</code> table. This example demonstrates a basic SELECT query to retrieve a complete list of accounts from Zoho CRM.</p>]]></Desc>
      <Code><![CDATA[SELECT * from Accounts]]></Code>
    </Example>

    <Example Group="ODBC" Slug="update-record-owner" Label="Update record owner">
      <Desc><![CDATA[<p>Updates the owner of a record (e.g., Account, Contact, Deal, Lead). This example shows how to update a lookup field like <code>Owner</code> using a unique identifier such as email or ID. In this case, the owner of a specific Account is updated by email.</p>]]></Desc>
      <Code>
        <![CDATA[UPDATE Accounts 
SET Owner='{email: "bob-the-salesman@abc.com"}'
--SET Owner='{id: "1558554000186378001"}' --you can also use Id
Where Id='1558554000137221573']]>
      </Code>
    </Example>
    <Example Group="ODBC" Slug="update-deal-account-contact" Label="Update deal account or contact">
      <Desc><![CDATA[<p>Updates the Account and Contact lookup fields for a Deal record. This example demonstrates setting the <code>Account_Name</code> by name and <code>Contact_Name</code> by ID for a specific Deal.</p>]]></Desc>
      <Code>
        <![CDATA[UPDATE Deals 
SET Account_Name='{"name": "Company ABCD"}',    --by name or id 
    Contact_Name='{"id": "1558554000186378001"}'  --by id 
Where Id='1558554000137221573']]>
      </Code>
    </Example>	

    <Example Group="ODBC" Slug="create-deal-lookup-fields" Label="Create a deal with lookup fields">
      <Desc><![CDATA[<p>Creates a new Deal record with lookup fields populated. This example demonstrates how to set <code>Account_Name</code>, <code>Contact_Name</code>, and <code>Owner</code> using their respective Names, IDs, or Emails during the INSERT operation.</p>]]></Desc>
      <Code>
        <![CDATA[
INSERT INTO Deals(
	Deal_name,
	Amount,
	Lead_Source,
	Account_Name,
	Contact_Name,
	Owner
	)
VALUES
   (
   'My Test Deal Creatyed on <<FUN_NOW>>', --deal name
   1000.50, --amount
   'Cold Call', --lead source
   '{name:"ZappySys"}', --account name or use id '{id:"1558554000030180013"}'
   '{id:"1558554000089352998"}', --contact id 
   '{id:"1558554000089352912"}' --owner id or use email {email: "bob-the-salesman@abc.com"}
   )
		]]>
      </Code>
    </Example>	
	

    <Example Group="ODBC" Slug="read-account-by-id" Label="Read an account by ID">
      <Desc><![CDATA[<p>Reads a single Account record by its ID. This example demonstrates filtering the <code>Accounts</code> table using the <code>WHERE</code> clause with a specific ID.</p>]]></Desc>
      <Code><![CDATA[SELECT * from Accounts Where Id=1558554000105110008]]></Code>
    </Example>
    <Example Group="ODBC" Slug="read-accounts-modified-after" Label="Read accounts modified after date">
      <Desc><![CDATA[<p>Reads Account records modified after a specified date and time. This example demonstrates using the <code>ModifiedSince</code> parameter in the <code>WITH</code> clause to perform an incremental fetch.</p>]]></Desc>
      <Code><![CDATA[SELECT * from Accounts WITH(ModifiedSince = '2020-01-07T00:00:00')]]></Code>
    </Example>
    <Example Group="ODBC" Slug="read-data-coql" Label="Read data using COQL (Native SQL)">
      <Desc><![CDATA[<p>Executes a COQL (CRM Object Query Language) query to retrieve data. This example demonstrates using the <code>get_module_data_coql</code> endpoint to run a server-side query, which can be more efficient than client-side filtering. Note that COQL queries have a limit of 200 rows.</p>]]></Desc>
      <Code><![CDATA[SELECT * from get_module_data_coql WITH(sql_query= 'select Last_Name, First_Name, Company from Leads where Company like ''Test'' limit 200')]]></Code>
    </Example>
    <Example Group="ODBC" Slug="update-lead" Label="Update a lead">
      <Desc><![CDATA[<p>Updates a specific Lead record. This example demonstrates modifying fields like <code>Designation</code> and <code>Company</code> for a Lead identified by its ID in the <code>WHERE</code> clause.</p>]]></Desc>
      <Code><![CDATA[Update Leads SET Designation='VP Sales', Company='Test' Where id=1558554000012181009]]></Code>
    </Example>
    <Example Group="ODBC" Slug="update-lead-legacy" Label="Update a lead (legacy)">
      <Desc><![CDATA[<p>Updates a specific Lead record using an alternative syntax. This example demonstrates passing the <code>id</code> as a column in the <code>SET</code> clause instead of using a <code>WHERE</code> clause.</p>]]></Desc>
      <Code><![CDATA[Update Leads SET id='1558554000012181009' /* id must be supplied */, Designation='VP Sales', Company='Test']]></Code>
    </Example>
    <Example Group="ODBC" Slug="read-accounts-filtered-date" Label="Read accounts modified after date (filtered)">
      <Desc><![CDATA[<p>Reads Account records matching a name pattern and modified after a specific date. This example combines a <code>WHERE</code> clause filter with the <code>ModifiedSince</code> parameter for targeted data retrieval.</p>]]></Desc>
      <Code><![CDATA[SELECT * from Accounts Where Account_Name LIKE 'Test%' WITH(ModifiedSince = '2020-01-07T00:00:00')]]></Code>
    </Example>
    <Example Group="ODBC" Slug="search-accounts-criteria" Label="Search accounts by criteria">
      <Desc><![CDATA[<p>Searches for Account records using specific criteria. This example demonstrates using the <code>search_Accounts</code> endpoint with the <code>criteria</code> parameter to perform a server-side search (e.g., accounts starting with "test").</p>]]></Desc>
      <Code><![CDATA[SELECT * FROM search_Accounts WITH(criteria='Account_Name:starts_with:test')]]></Code>
    </Example>

    <Example Group="ODBC" Slug="create-account" Label="Create an account">
      <Desc><![CDATA[<p>Creates a new Account record. This example demonstrates using the <code>INSERT INTO</code> statement to add a new account with <code>Account_Name</code> and <code>Phone</code>.</p>]]></Desc>
      <Code><![CDATA[INSERT INTO Accounts(Account_Name, Phone) VALUES('Company ABC','111-567-8888')]]></Code>
    </Example>
    <Example Group="ODBC" Slug="create-account-output" Label="Create an account (with output)">
      <Desc><![CDATA[<p>Creates a new Account record and returns the created record's details. This example uses <code>WITH(Output=1)</code> to display the result of the INSERT operation.</p>]]></Desc>
      <Code><![CDATA[INSERT INTO Accounts(Account_Name, Phone) VALUES('Company ABC','111-567-8888') WITH(Output=1) ]]></Code>
    </Example>
    <Example Group="ODBC" Slug="delete-account" Label="Delete an account">
      <Desc><![CDATA[<p>Deletes a single Account record by its ID. This example demonstrates using the <code>DELETE FROM</code> statement with a <code>WHERE</code> clause specifying the record ID.</p>]]></Desc>
      <Code><![CDATA[DELETE FROM Accounts WHERE id=11111111111]]></Code>
    </Example>

    <Example Group="ODBC" Slug="delete-accounts-bulk" Label="Delete accounts in bulk">
      <Desc><![CDATA[<p>Deletes multiple Account records by specifying a list of IDs. This example demonstrates passing a comma-separated list of IDs to the <code>Id</code> parameter in the <code>WITH</code> clause (up to 100 IDs).</p>]]></Desc>
      <Code><![CDATA[DELETE FROM Accounts WITH(Id='11111,22222,33333')]]></Code>
    </Example>

	
    <Example Group="ODBC" Slug="upsert-account" Label="Upsert an account">
      <Desc><![CDATA[<p>Updates or inserts an Account record. This example demonstrates using the <code>UPSERT INTO</code> statement, which checks for existing records based on unique fields before deciding to update or insert.</p>]]></Desc>
      <Code><![CDATA[UPSERT INTO Accounts(Account_Name, Phone) VALUES('Company ABC','111-567-8888') WITH(Output=1)]]></Code>
    </Example>
	
    <Example Group="ODBC" Slug="upsert-lead" Label="Upsert a lead">
      <Desc><![CDATA[<p>Updates or inserts a Lead record. This example demonstrates using the <code>UPSERT INTO</code> statement for Leads, updating based on unique fields like Email.</p>]]></Desc>
      <Code><![CDATA[UPSERT INTO Leads(Last_Name, Email) VALUES('Patel','zpatel@abc.com') WITH(Output=1)]]></Code>
    </Example>	

    <Example Group="ODBC" Slug="bulk-create-accounts-sql-server" Label="Bulk create accounts using SQL Server data">
      <Desc><![CDATA[<p>Creates multiple Account records in bulk using data from a SQL Server database. This example demonstrates using the <code>SOURCE</code> clause to read data from an external ODBC/OLEDB source and insert it into Zoho CRM.</p>]]></Desc>
      <Code>
        <![CDATA[INSERT INTO Accounts
SOURCE(
  'MSSQL' --ODBC or OLEDB
  ,'Data Source=localhost;Initial Catalog=Test;Integrated Security=true'
  ,'select ''Test Account-A'' as Account_Name,''111-111-1111'' as Phone
    UNION
    select ''Test Account-B'' as Account_Name,''222-222-2222'' as Phone
   '
)]]>
      </Code>
    </Example>

    <Example Group="ODBC" Slug="bulk-upsert-accounts-sql-server" Label="Bulk upsert accounts using SQL Server data">
      <Desc><![CDATA[<p>Upserts multiple Account records in bulk using data from a SQL Server database. This example demonstrates using the <code>SOURCE</code> clause with <code>UPSERT INTO</code> to synchronize data from an external source to Zoho CRM.</p>]]></Desc>
      <Code>
        <![CDATA[UPSERT INTO Accounts
SOURCE(
  'MSSQL' --ODBC or OLEDB
  ,'Data Source=localhost;Initial Catalog=Test;Integrated Security=true'
  ,'select ''Test Account-A'' as Account_Name,''111-111-1111'' as Phone
    UNION
    select ''Test Account-B'' as Account_Name,''222-222-2222'' as Phone
   '
)]]>
      </Code>
    </Example>

    <Example Group="ODBC" Slug="update-tags" Label="Update tags">
      <Desc><![CDATA[<p>Adds or overwrites tags for existing records. This example demonstrates using the <code>post_tags</code> endpoint to update tags for a specific record ID in the Accounts module.</p>]]></Desc>
      <Code>
        <![CDATA[SELECT * FROM post_tags
WITH(
	  module='Accounts'
	, ids='1558554000105151002'
	, tag_names='mytag1,mytag2'
  , over_write='true'
)]]>
      </Code>
    </Example>
  </Examples>
</ApiConfig>