For Zoho Services only:


I'm actually part of something bigger at Ascent Business Solutions recognized as the top Zoho Premium Solutions Partner in the United Kingdom.

Ascent Business Solutions offer support for smaller technical fixes and projects for larger developments, such as migrating to a ZohoCRM.  A team rather than a one-man-band is always available to ensure seamless progress and address any concerns. You'll find our competitive support rates with flexible, no-expiration bundles at http://ascentbusiness.co.uk/zoho-support-2.  For larger projects, check our bespoke pricing structure and receive dedicated support from our hands-on project consultants and developers at http://ascentbusiness.co.uk/crm-solutions/zoho-crm-packages-prices.

The team I manage specializes in coding API integrations between Zoho and third-party finance/commerce suites such as Xero, Shopify, WooCommerce, and eBay; to name but a few.  Our passion lies in creating innovative solutions where others have fallen short as well as working with new businesses, new sectors, and new ideas.  Our success is measured by the growth and ROI we deliver for clients, such as transforming a garden shed hobby into a 250k monthly turnover operation or generating a +60% return in just three days after launch through online payments and a streamlined e-commerce solution, replacing a paper-based system.

If you're looking for a partner who can help you drive growth and success, we'd love to work with you.  You can reach out to us on 0121 392 8140 (UK) or info@ascentbusiness.co.uk.  You can also visit our website at http://ascentbusiness.co.uk.

Zoho Webhooks & Shopify API: Keep Disappearing

What?
This is an article to show how to setup a scheduled function that checks and restores a missing webhook as well as the snippets when receiving the webhooks and storing them.

Why?
We found that Shopify would intermittently remove our webhooks. This would make the entire synchronization of the system go out of whack and some records would slip through the net while every day, the process to tidy these all up would leave the data more and more unreliable.

So Shopify want your webhooks to respond within 1 second. This is about enough time to store the record but that's it. Processing the record must be done at a later time or in a different process but sometimes it simply will not process it all and respond to Shopify within 1 second.

How?
So let's begin with the code snippets as these might answer your question to begin with and then we'll do the easy bit on how you set this up in the CRM. I'm using ZohoCRM here despite storing the record in ZohoCreator as the app and data processing is mostly done in ZohoCreator. I could have setup webhooks to go directly to Zoho Creator but I don't find Zoho Creator reliable when receiving and responding to webhooks.

Important!: For the REST API to detect what webhooks exist, it can only detect what webhooks it initialized. If you added webhooks via another app or via the Shopify Admin interface, then the following code won't be able to check and restore them.

The Code Snippets: The Shopify Order Update notification
First create a CRM function called Shopify - Webhook - Order Notification. It's a standalone function but you'll need to hover the mouse over it after creating the function so that you can enable the REST API endpoint of it. This will need to be triggered whenever there is an update to the order (especially when tracking details are changed on the order).
copyraw
/* *******************************************************************************
Function:       fn_Shopify_Webhook_OrderUpdate
Label:          Shopify - Webhook - Order Update
Trigger:        Function executed when a webhook from Shopify is sent to ZohoCRM (Order Update)
Inputs:         String crmAPIRequest
Outputs:        String crmAPIResponse

Date Created:   2022-01-17 (Joel Lipman)
                - Initial release
                - Forwards webhook to Zoho Creator
Date Modified:  2024-04-22 (Joel Lipman)
                - Minimized amount of processing to simply storing the record in Zoho
                - Run HMAC SHA 256 verification
******************************************************************************* */
//
// need to respond in less than 1 second
m_Payload = crmAPIRequest.toMap();
m_Blank = Map();
//
// you created an app that generated a client ID and a client secret and resulted in an access token
// the client secret used when generating the access token should be entered here
v_ClientSecret = "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";
//
// store the record in ZohoCreator 
// I have a custom form in ZC with the fields "Event_Type" (single-line) and "JSON_Payload" (multi-line)
m_CreateRecord = Map();
m_CreateRecord.put("Event_Type","Order Update");
m_CreateRecord.put("JSON_Payload",m_Payload.toString());
r_CreateRecord = zoho.creator.createRecord("myOwnerName","myAppName","myFormName",m_CreateRecord,m_Blank,"myCreatorConnection");
//
// build the hash based on the payload body
v_Data = ifnull(m_Payload.get("body"),"");
v_VerifyHash = zoho.encryption.hmacsha256(v_ClientSecret,v_Data,"base64");
//
// retrieve Shopify's Hmac SHA256 from the header
v_ShopifyHash = "";
if(m_Payload.get("headers") != null)
{
	if(m_Payload.get("headers").get("x-shopify-hmac-sha256") != null)
	{
		v_ShopifyHash = m_Payload.get("headers").get("x-shopify-hmac-sha256");
	}
}
//
// build response to Shopify
m_ResponseHeader = Map();
m_ResponseHeader.put("status_code",401);
//
// compare our hash vs the received hash
if(v_VerifyHash == v_ShopifyHash)
{
	m_ResponseHeader.put("status_code",200);
}
//
// respond
return {"crmAPIResponse":m_ResponseHeader};
  1.  /* ******************************************************************************* 
  2.  Function:       fn_Shopify_Webhook_OrderUpdate 
  3.  Label:          Shopify - Webhook - Order Update 
  4.  Trigger:        Function executed when a webhook from Shopify is sent to ZohoCRM (Order Update) 
  5.  Inputs:         string crmAPIRequest 
  6.  Outputs:        string crmAPIResponse 
  7.   
  8.  Date Created:   2022-01-17 (Joel Lipman) 
  9.                  - Initial release 
  10.                  - Forwards webhook to Zoho Creator 
  11.  Date Modified:  2024-04-22 (Joel Lipman) 
  12.                  - Minimized amount of processing to simply storing the record in Zoho 
  13.                  - Run HMAC SHA 256 verification 
  14.  ******************************************************************************* */ 
  15.  // 
  16.  // need to respond in less than 1 second 
  17.  m_Payload = crmAPIRequest.toMap()
  18.  m_Blank = Map()
  19.  // 
  20.  // you created an app that generated a client ID and a client secret and resulted in an access token 
  21.  // the client secret used when generating the access token should be entered here 
  22.  v_ClientSecret = "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"
  23.  // 
  24.  // store the record in ZohoCreator 
  25.  // I have a custom form in ZC with the fields "Event_Type" (single-line) and "JSON_Payload" (multi-line) 
  26.  m_CreateRecord = Map()
  27.  m_CreateRecord.put("Event_Type","Order Update")
  28.  m_CreateRecord.put("JSON_Payload",m_Payload.toString())
  29.  r_CreateRecord = zoho.creator.createRecord("myOwnerName","myAppName","myFormName",m_CreateRecord,m_Blank,"myCreatorConnection")
  30.  // 
  31.  // build the hash based on the payload body 
  32.  v_Data = ifnull(m_Payload.get("body"),"")
  33.  v_VerifyHash = zoho.encryption.hmacsha256(v_ClientSecret,v_Data,"base64")
  34.  // 
  35.  // retrieve Shopify's Hmac SHA256 from the header 
  36.  v_ShopifyHash = ""
  37.  if(m_Payload.get("headers") != null) 
  38.  { 
  39.      if(m_Payload.get("headers").get("x-shopify-hmac-sha256") != null) 
  40.      { 
  41.          v_ShopifyHash = m_Payload.get("headers").get("x-shopify-hmac-sha256")
  42.      } 
  43.  } 
  44.  // 
  45.  // build response to Shopify 
  46.  m_ResponseHeader = Map()
  47.  m_ResponseHeader.put("status_code",401)
  48.  // 
  49.  // compare our hash vs the received hash 
  50.  if(v_VerifyHash == v_ShopifyHash) 
  51.  { 
  52.      m_ResponseHeader.put("status_code",200)
  53.  } 
  54.  // 
  55.  // respond 
  56.  return {"crmAPIResponse":m_ResponseHeader}

The Code Snippets: The Shopify Inventory Level Update notification
Note that this one is not the "Inventory Item Update" as I get the two muddled up very often and they don't do the same thing. We want this triggered whenever the stock level of a product changes.
copyraw
/* *******************************************************************************
Function:       fn_Shopify_Webhook_InventoryLevelUpdate(String crmAPIRequest)
Label:          Shopify - Webhook - Inventory Level Update
Trigger:        Function executed when a webhook from Shopify is sent to ZohoCRM (Inventory Update)
Inputs:         String crmAPIRequest
Outputs:        String crmAPIResponse
******************************************************************************* */
//
// need to respond in less than 1 second
m_Payload = crmAPIRequest.toMap();
m_Blank = Map();
//
// you created an app that generated a client ID and a client secret and resulted in an access token
// the client secret used when generating the access token should be entered here
v_ClientSecret = "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";
//
// store the record in ZohoCreator 
// I have a custom form in ZC with the fields "Event_Type" (single-line) and "JSON_Payload" (multi-line)
m_CreateRecord = Map();
m_CreateRecord.put("Event_Type","Order Update");
m_CreateRecord.put("JSON_Payload",m_Payload.toString());
r_CreateRecord = zoho.creator.createRecord("myOwnerName","myAppName","myFormName",m_CreateRecord,m_Blank,"myCreatorConnection");
//
v_Data = ifnull(m_Payload.get("body"),"");
v_VerifyHash = zoho.encryption.hmacsha256(v_ClientSecret,v_Data,"base64");
//
// retrieve Shopify's Hmac SHA256
v_ShopifyHash = "";
if(m_Payload.get("headers") != null)
{
	if(m_Payload.get("headers").get("x-shopify-hmac-sha256") != null)
	{
		v_ShopifyHash = m_Payload.get("headers").get("x-shopify-hmac-sha256");
	}
}
//
// build response to Shopify
m_ResponseHeader = Map();
m_ResponseHeader.put("status_code",401);
//
// compare our hash vs the received hash
if(v_VerifyHash == v_ShopifyHash)
{
	m_ResponseHeader.put("status_code",200);
}
/*
//
sendmail
[
	from :zoho.adminuserid
	to :"This email address is being protected from spambots. You need JavaScript enabled to view it."
	subject :"CLIENT Payload and Hash Comparison"
	message :v_VerifyHash + "" + v_ShopifyHash + "" + m_Payload.toString()
]
//
// to cut even more time, we could store it directly in ZohoCRM and have a CRM workflow/automation forward it to Zoho Creator.
m_WebhookLog = Map();
m_WebhookLog.put("Name","Shopify - Inventory Update - " + zoho.currenttime.toString("yyyy-MM-dd HH:mm","Europe/London"));
m_WebhookLog.put("Body",m_Payload.get("body"));
m_WebhookLog.put("Event_Type","Inventory Update");
m_WebhookLog.put("Source","Shopify");
m_WebhookLog.put("Data_Format","JSON");
r_WebhookLog = zoho.crm.createRecord("Webhook_Payloads",m_WebhookLog);
*/
return {"crmAPIResponse":m_ResponseHeader};
  1.  /* ******************************************************************************* 
  2.  Function:       fn_Shopify_Webhook_InventoryLevelUpdate(String crmAPIRequest) 
  3.  Label:          Shopify - Webhook - Inventory Level Update 
  4.  Trigger:        Function executed when a webhook from Shopify is sent to ZohoCRM (Inventory Update) 
  5.  Inputs:         string crmAPIRequest 
  6.  Outputs:        string crmAPIResponse 
  7.  ******************************************************************************* */ 
  8.  // 
  9.  // need to respond in less than 1 second 
  10.  m_Payload = crmAPIRequest.toMap()
  11.  m_Blank = Map()
  12.  // 
  13.  // you created an app that generated a client ID and a client secret and resulted in an access token 
  14.  // the client secret used when generating the access token should be entered here 
  15.  v_ClientSecret = "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"
  16.  // 
  17.  // store the record in ZohoCreator 
  18.  // I have a custom form in ZC with the fields "Event_Type" (single-line) and "JSON_Payload" (multi-line) 
  19.  m_CreateRecord = Map()
  20.  m_CreateRecord.put("Event_Type","Order Update")
  21.  m_CreateRecord.put("JSON_Payload",m_Payload.toString())
  22.  r_CreateRecord = zoho.creator.createRecord("myOwnerName","myAppName","myFormName",m_CreateRecord,m_Blank,"myCreatorConnection")
  23.  // 
  24.  v_Data = ifnull(m_Payload.get("body"),"")
  25.  v_VerifyHash = zoho.encryption.hmacsha256(v_ClientSecret,v_Data,"base64")
  26.  // 
  27.  // retrieve Shopify's Hmac SHA256 
  28.  v_ShopifyHash = ""
  29.  if(m_Payload.get("headers") != null) 
  30.  { 
  31.      if(m_Payload.get("headers").get("x-shopify-hmac-sha256") != null) 
  32.      { 
  33.          v_ShopifyHash = m_Payload.get("headers").get("x-shopify-hmac-sha256")
  34.      } 
  35.  } 
  36.  // 
  37.  // build response to Shopify 
  38.  m_ResponseHeader = Map()
  39.  m_ResponseHeader.put("status_code",401)
  40.  // 
  41.  // compare our hash vs the received hash 
  42.  if(v_VerifyHash == v_ShopifyHash) 
  43.  { 
  44.      m_ResponseHeader.put("status_code",200)
  45.  } 
  46.  /* 
  47.  // 
  48.  sendmail 
  49.  [ 
  50.      from :zoho.adminuserid 
  51.      to :"me+This email address is being protected from spambots. You need JavaScript enabled to view it.
  52.      subject :"CLIENT Payload and Hash Comparison" 
  53.      message :v_VerifyHash + "" + v_ShopifyHash + "" + m_Payload.toString() 
  54.  ] 
  55.  // 
  56.  // to cut even more time, we could store it directly in ZohoCRM and have a CRM workflow/automation forward it to Zoho Creator. 
  57.  m_WebhookLog = Map()
  58.  m_WebhookLog.put("Name","Shopify - Inventory Update - + zoho.currenttime.toString("yyyy-MM-dd HH:mm","Europe/London"))
  59.  m_WebhookLog.put("Body",m_Payload.get("body"))
  60.  m_WebhookLog.put("Event_Type","Inventory Update")
  61.  m_WebhookLog.put("Source","Shopify")
  62.  m_WebhookLog.put("Data_Format","JSON")
  63.  r_WebhookLog = zoho.crm.createRecord("Webhook_Payloads",m_WebhookLog)
  64.  */ 
  65.  return {"crmAPIResponse":m_ResponseHeader}

The Code Snippets: The Shopify Webhook Check and Restore
If you notice your webhooks automatically being removed. It's often because you have it processing data rather than responding straight away (less than 1 second requirement) to Shopify with "yes received" response.

As such, here's a function which lists the Shopify webhooks it's responsible for and if it finds one missing, it is to restore it. This function only has to check on 2 webhooks: the order update and the inventory level update:
copyraw
/* *******************************************************************************
Function:       String fn_Shopify_RestoreWebhook()
Label:          Fn - Shopify - Restore Webhook
Trigger:        Scheduled function to check on Shopify webhooks and to restore them if they have been removed.
Inputs:         -
Outputs:        -

Date Created:   2024-04-22 (Joel Lipman)
                - Initial release
Date Modified:  ???
                - ???
******************************************************************************* */
// 
// set your own REST API endpoints for the webhooks here (we are only checking order update or inventory level update)
v_CrmOrderUpdateWebhook = "https://www.zohoapis.com/crm/v2/functions/fn_shopify_webhook_orderupdate/actions/execute?auth_type=apikey&zapikey=1003.aaaabbbbccccddddeeeeffff00001111.22223333444455556666777788889999";
v_CrmInventoryLevelWebhook = "https://www.zohoapis.com/crm/v2/functions/fn_shopify_webhook_inventorylevelupdate/actions/execute?auth_type=apikey&zapikey=1003.aaaabbbbccccddddeeeeffff00001111.22223333444455556666777788889999";
// 
// restore by default
b_RestoreOrderUpdateWebhook = true;
b_RestoreInventoryLevelWebhook = true;
//
// retrieve connection details record
r_ShopifyConnection = zoho.creator.getRecordById("myOwnerName","myAppName","myAPIConnectionsData",<myAPIConnectionRecordID>,"myCreatorConnection");
//
// resolve connection details
if(!isNull(r_ShopifyConnection.get("data")))
{
	m_Data = r_ShopifyConnection.get("data");
	v_ShopifyID = ifnull(m_Data.get("Shop_ID"),"");
	v_APIVersion = ifnull(m_Data.get("API_Version"),"");
	v_AccessToken = ifnull(m_Data.get("Access_Token"),"");
	//
	m_Header = Map();
	m_Header.put("X-Shopify-Access-Token",v_AccessToken);
	m_Header.put("Content-Type","application/json");
	//
	// list all webhooks (note these are only webhooks created by apps, not added to Shopify manually)
	v_Endpoint = "https://" + v_ShopifyID + "/admin/api/" + v_APIVersion + "/webhooks.json";
	r_ShopifyWebhooks = invokeurl
	[
		url :v_Endpoint
		type :GET
		headers:m_Header
	];
	if(r_ShopifyWebhooks.get("webhooks") != null)
	{
		// 
		// loop through to see if our custom notifications exist
		// note that installing other apps may create similar webhooks so you need to make sure the script below is looking for your custom webhook
		for each  m_ThisWebhook in r_ShopifyWebhooks.get("webhooks")
		{
			if(m_ThisWebhook.get("id") != null)
			{
				//
				// my app is the only one using the orders/updated webhook topic/trigger
				if(m_ThisWebhook.get("topic").equalsIgnoreCase("orders/updated"))
				{
					b_RestoreOrderUpdateWebhook = false;
				}
				//
				// my app is the only one using the inventory_levels/update webhook topic/trigger
				if(m_ThisWebhook.get("topic").equalsIgnoreCase("inventory_levels/update"))
				{
					b_RestoreInventoryLevelWebhook = false;
				}
			}
		}
	}
	//
	// create order update webhook
	if(b_RestoreOrderUpdateWebhook)
	{
		m_Webhook = Map();
		m_Webhook.put("format","json");
		m_Webhook.put("topic","orders/updated");
		m_Webhook.put("address",v_CrmOrderUpdateWebhook);
		m_Params = Map();
		m_Params.put("webhook",m_Webhook);
		//
		v_Endpoint = "https://" + v_ShopifyID + "/admin/api/" + v_APIVersion + "/webhooks.json";
		r_ShopifyOrderWebhook = invokeurl
		[
			url :v_Endpoint
			type :POST
			parameters:m_Params.toString()
			headers:m_Header
		];
	}
	//
	// create inventory level update webhook
	if(b_RestoreInventoryLevelWebhook)
	{
		m_Webhook = Map();
		m_Webhook.put("format","json");
		m_Webhook.put("topic","inventory_levels/update");
		m_Webhook.put("address",v_CrmInventoryLevelWebhook);
		m_Params = Map();
		m_Params.put("webhook",m_Webhook);
		//
		v_Endpoint = "https://" + v_ShopifyID + "/admin/api/" + v_APIVersion + "/webhooks.json";
		r_ShopifyInventoryWebhook = invokeurl
		[
			url :v_Endpoint
			type :POST
			parameters:m_Params.toString()
			headers:m_Header
		];
	}
}
return r_ShopifyWebhooks;
  1.  /* ******************************************************************************* 
  2.  Function:       string fn_Shopify_RestoreWebhook() 
  3.  Label:          Fn - Shopify - Restore Webhook 
  4.  Trigger:        Scheduled function to check on Shopify webhooks and to restore them if they have been removed. 
  5.  Inputs:         - 
  6.  Outputs:        - 
  7.   
  8.  Date Created:   2024-04-22 (Joel Lipman) 
  9.                  - Initial release 
  10.  Date Modified:  ??? 
  11.                  - ??? 
  12.  ******************************************************************************* */ 
  13.  // 
  14.  // set your own REST API endpoints for the webhooks here (we are only checking order update or inventory level update) 
  15.  v_CrmOrderUpdateWebhook = "https://www.zohoapis.com/crm/v2/functions/fn_shopify_webhook_orderupdate/actions/execute?auth_type=apikey&zapikey=1003.aaaabbbbccccddddeeeeffff00001111.22223333444455556666777788889999"
  16.  v_CrmInventoryLevelWebhook = "https://www.zohoapis.com/crm/v2/functions/fn_shopify_webhook_inventorylevelupdate/actions/execute?auth_type=apikey&zapikey=1003.aaaabbbbccccddddeeeeffff00001111.22223333444455556666777788889999"
  17.  // 
  18.  // restore by default 
  19.  b_RestoreOrderUpdateWebhook = true
  20.  b_RestoreInventoryLevelWebhook = true
  21.  // 
  22.  // retrieve connection details record 
  23.  r_ShopifyConnection = zoho.creator.getRecordById("myOwnerName","myAppName","myAPIConnectionsData",<myAPIConnectionRecordID>,"myCreatorConnection")
  24.  // 
  25.  // resolve connection details 
  26.  if(!isNull(r_ShopifyConnection.get("data"))) 
  27.  { 
  28.      m_Data = r_ShopifyConnection.get("data")
  29.      v_ShopifyID = ifnull(m_Data.get("Shop_ID"),"")
  30.      v_APIVersion = ifnull(m_Data.get("API_Version"),"")
  31.      v_AccessToken = ifnull(m_Data.get("Access_Token"),"")
  32.      // 
  33.      m_Header = Map()
  34.      m_Header.put("X-Shopify-Access-Token",v_AccessToken)
  35.      m_Header.put("Content-Type","application/json")
  36.      // 
  37.      // list all webhooks (note these are only webhooks created by apps, not added to Shopify manually) 
  38.      v_Endpoint = "https://" + v_ShopifyID + "/admin/api/" + v_APIVersion + "/webhooks.json"
  39.      r_ShopifyWebhooks = invokeUrl 
  40.      [ 
  41.          url :v_Endpoint 
  42.          type :GET 
  43.          headers:m_Header 
  44.      ]
  45.      if(r_ShopifyWebhooks.get("webhooks") != null) 
  46.      { 
  47.          // 
  48.          // loop through to see if our custom notifications exist 
  49.          // note that installing other apps may create similar webhooks so you need to make sure the script below is looking for your custom webhook 
  50.          for each  m_ThisWebhook in r_ShopifyWebhooks.get("webhooks") 
  51.          { 
  52.              if(m_ThisWebhook.get("id") != null) 
  53.              { 
  54.                  // 
  55.                  // my app is the only one using the orders/updated webhook topic/trigger 
  56.                  if(m_ThisWebhook.get("topic").equalsIgnoreCase("orders/updated")) 
  57.                  { 
  58.                      b_RestoreOrderUpdateWebhook = false
  59.                  } 
  60.                  // 
  61.                  // my app is the only one using the inventory_levels/update webhook topic/trigger 
  62.                  if(m_ThisWebhook.get("topic").equalsIgnoreCase("inventory_levels/update")) 
  63.                  { 
  64.                      b_RestoreInventoryLevelWebhook = false
  65.                  } 
  66.              } 
  67.          } 
  68.      } 
  69.      // 
  70.      // create order update webhook 
  71.      if(b_RestoreOrderUpdateWebhook) 
  72.      { 
  73.          m_Webhook = Map()
  74.          m_Webhook.put("format","json")
  75.          m_Webhook.put("topic","orders/updated")
  76.          m_Webhook.put("address",v_CrmOrderUpdateWebhook)
  77.          m_Params = Map()
  78.          m_Params.put("webhook",m_Webhook)
  79.          // 
  80.          v_Endpoint = "https://" + v_ShopifyID + "/admin/api/" + v_APIVersion + "/webhooks.json"
  81.          r_ShopifyOrderWebhook = invokeUrl 
  82.          [ 
  83.              url :v_Endpoint 
  84.              type :POST 
  85.              parameters:m_Params.toString() 
  86.              headers:m_Header 
  87.          ]
  88.      } 
  89.      // 
  90.      // create inventory level update webhook 
  91.      if(b_RestoreInventoryLevelWebhook) 
  92.      { 
  93.          m_Webhook = Map()
  94.          m_Webhook.put("format","json")
  95.          m_Webhook.put("topic","inventory_levels/update")
  96.          m_Webhook.put("address",v_CrmInventoryLevelWebhook)
  97.          m_Params = Map()
  98.          m_Params.put("webhook",m_Webhook)
  99.          // 
  100.          v_Endpoint = "https://" + v_ShopifyID + "/admin/api/" + v_APIVersion + "/webhooks.json"
  101.          r_ShopifyInventoryWebhook = invokeUrl 
  102.          [ 
  103.              url :v_Endpoint 
  104.              type :POST 
  105.              parameters:m_Params.toString() 
  106.              headers:m_Header 
  107.          ]
  108.      } 
  109.  } 
  110.  return r_ShopifyWebhooks; 

The REST API endpoints
If you are having difficulty finding these, go to your CRM > Settings/Setup > Functions: then hover your mouse over the function and select "REST API". Enable the API Key option and copy the long URL to your clipboard for use in the above function:
ZohoCRM: Getting REST API endpoint to invoke the function

Set up a schedule
If you find your webhooks being automatically removed by Shopify, then we put this schedule in to run as many times as possible during the day (but not enough to be banned):
  1. Login to ZohoCRM > Setup > Automation > Schedules > Create New Schedule
  2. I'm calling my schedule "Shopify - Check Webhooks" and I'm going to execute a writing function.
  3. It has a function name of "fn_Schedule_ShopifyWebhooks" and a display name of "Schedule - Shopify Webhooks"
  4. It has the code
    copyraw
    standalone.fn_Shopify_RestoreWebhook();
    1.  standalone.fn_Shopify_RestoreWebhook()
  5. Starts ASAP; with a frequency of Hourly (run every 2 hours); and never ends.
  6. Save and done.


Error(s) Encountered
  • webhook: expected String to be a Hash In this invokeURL, set the parameters to a JSON string using .toString().
  • For those puzzled as to how you setup a webhook function in ZohoCRM: Create a function with a string parameter called "crmAPIRequest". It has to have this name. It is a reserved variable and will contain all the webhook payload data. When a webhook is pointed at it, the crmAPIRequest variable will hold the payload. Same with responding with the variable crmAPIResponse. Don't overthink it, just accept it. Less headaches for everyone.

Source(s):

Category: Zoho :: Article: 872

Credit where Credit is Due:


Feel free to copy, redistribute and share this information. All that we ask is that you attribute credit and possibly even a link back to this website as it really helps in our search engine rankings.

Disclaimer: Please note that the information provided on this website is intended for informational purposes only and does not represent a warranty. The opinions expressed are those of the author only. We recommend testing any solutions in a development environment before implementing them in production. The articles are based on our good faith efforts and were current at the time of writing, reflecting our practical experience in a commercial setting.

Thank you for visiting and, as always, we hope this website was of some use to you!

Kind Regards,

Joel Lipman
www.joellipman.com

Related Articles

Joes Revolver Map

Accreditation

Badge - Certified Zoho Creator Associate
Badge - Certified Zoho Creator Associate

Donate & Support

If you like my content, and would like to support this sharing site, feel free to donate using a method below:

Paypal:
Donate to Joel Lipman via PayPal

Bitcoin:
Donate to Joel Lipman with Bitcoin bc1qf6elrdxc968h0k673l2djc9wrpazhqtxw8qqp4

Ethereum:
Donate to Joel Lipman with Ethereum 0xb038962F3809b425D661EF5D22294Cf45E02FebF
© 2024 Joel Lipman .com. All Rights Reserved.