Serverless Functions - Using API Key

API Keys of functions

A severless function within your CRM can be invoked from any third-party application or within the CRM using a webhook. However, generally most of the webhooks do not support OAuth2, save for a few of them. In that case, you can execute the function using the API Key authentication method, which can be used by either you or others to invoke the function from anywhere.

The difference between API Key and OAuth2 lies in the mode of authentication. API Key has to be authenticated in the Request URL and not as a header.

See also:

Sample Function:

Scenario:

Helpdesk and support-related softwares are an absolute essential in a business which involves interaction with customers and clients. Integrating your help desk softwares with your CRM saves up a lot of time and effort to manage all your business information from a single place.

Zendesk is one such software. Zoho Desk, developed by Zoho, is also one, but the difference is that Zoho Desk integration is made automatic in Zoho CRM, whereas you need to integrate Zendesk only through Widgets. Furthermore, when you need to transfer the ticket information from one helpdesk to another, you need to go to great lengths. Hence an integration of Zendesk and Zoho Desk, through Serverless Functions in Zoho CRM, is pretty convenient and useful.

The scenario which we are going to assume now is similar. Whenever a "Ticket" is created in "Zendesk", a ticket should be created in Zoho Desk as well, with the same information.

Required Applications:

  • Zendesk
  • Zoho Desk

Part 1: Make a Connection

In order for the Function to make use of third-party applications and facilitate data transfer, you need to first set up a connection between Zoho CRM and the said third-party software. In this case, it would be Zendesk. Read more.

Create a connection to Zoho Desk:

Part 2: Create the function

Create a function in Zoho CRM(inclusive of the code from the Connection).

Part 2.1: Write the function

The Function code is:

+

string createTicket(string requestBody){
  if(isNull(requestBody))
  {
    return "No Content";
  }
  if(!requestBody.contains("arguments"))
  {
    return "Invalid Format";
  }
  requestBody = requestBody.get("arguments");
  requestBody = requestBody.get("requestBody");
  requestBody = requestBody.get("details");
  deskURL = "https://desk.zoho.com/api/v1/";
  header = {"orgId":"664950682"};
  departmentId = "264631000000006907"; //Get ticket and user details from requestBody
  userDetails = requestBody.get("user");
  ticketDetails = requestBody.get("ticket"); //Create map
  param = Map(); //Insert Details
  param.put("departmentId",departmentId);
  if(!userDetails.contains("email"))
  {
    return "Email is Mandatory";
  }
  email = userDetails.get("email");
  param.put("email",email);
  contactName = "Guest";
  if(userDetails.contains("full_name"))
  {
    contactName = userDetails.get("full_name");
  }
  else if(userDetails.contains("first_name") && userDetails.contains("last_name"))
  {
    contactName = userDetails.get("first_name") + " " + userDetails.contains("last_name");
  }
  else if(userDetails.contains("first_name"))
  {
    contactName = userDetails.get("first_name");
  }
  else if(userDetails.contains("last_name"))
  {
    contactName = userDetails.get("last_name");
  }
  //Get Contact ID from Contact name
  //Get all Contacts
  contactList = invokeurl
  [
    url :deskURL + "contacts"
    type :GET
    headers:header
    connection:"zoho_desk9"
  ];
  isExistingCustomer = false;
  contactId = "";
  contactList = contactList.get("data");
  for each contactInfo in contactList
  {
    contactEmail = contactInfo.get("email");
    if(!isNull(contactEmail))
    {
      if(email.equals(contactEmail))
      {
        isExistingCustomer = true;
        contactId = contactInfo.get("contactId");
        break;
      }
    }
  }
  info isExistingCustomer;
  if(!isExistingCustomer)
  {
    //Create a new Contact
    contactParam = Map();
    contactParam.put("firstName",userDetails.get("first_name"));
    contactParam.put("lastName",userDetails.get("last_name"));
    contactParam.put("mobile",userDetails.get("mobile"));
    contactParam.put("email",userDetails.get("email"));
    contactParam.put("accountId","264631000000081178");
    contactList = invokeurl
    [
      url :deskURL + "contacts"
      type :POST
      parameters:contactParam.toString()
      headers:header
      connection:"zoho_desk9"
    ];
    contactId = contactList.get("id");
  }
  param.put("contactId",contactId);
  if(!ticketDetails.contains("title"))
  {
    return "title is mandatory";
  }
  param.put("subject",ticketDetails.get("title"));
  if(!ticketDetails.contains("status"))
  {
    return "status is mandatory";
  }
  param.put("status",ticketDetails.get("status"));
  if(ticketDetails.contains("priority"))
  {
    param.put("priority",ticketDetails.get("priority"));
  }
  if(userDetails.contains("organization"))
  {
    organization = userDetails.get("organization");
    if(organization.contains("name"))
    {
      param.put("accountName",organization.get("name"));
    }
  }
  if(userDetails.contains("mobile"))
  {
    param.put("phone",userDetails.get("mobile"));
  }
  if(userDetails.contains("description"))
  {
    param.put("description",userDetails.get("description"));
  }
  info param;
  response = invokeurl
  [
    url :deskURL + "tickets"
    type :POST
    parameters:param.toString()
    headers:header
    connection:"zoho_desk9"
  ];
  if(response.contains("errorMessage"))
  {
    return "Sorry Something went wrong. error ::: " + response.get("errorMessage");
  }
  //Send Notification to Suppot Team
  sendmail
  [
    from :zoho.adminuserid
    to :"deborah.g@zohocorp.com"
    subject :"no-reply"
    message :"'Dear Team,<expression></expression><div><br></div><div>A New Ticket is created inside Zoho DESK through Zendesk.</div><div><br></div><div>Ticket Details - </div><div><br></div><div>User Name - ' + contactName + '</div><div><br></div><div><br></div><div>Request Body = " + requestBody + "</div><div><br></div>'"
  ]
  return response;
}

 

Part2.2: To make the function available as an API Key:

  1. Click the Settings icon for the corresponding function which needs to be made an API.
  2. Click REST API.
  3. Enable API Key slider.
  4. Click Save.

Note:

  • This API key is static, and does not expire unless revoked.
  • You can regenerate the API key any time by clicking the Regenerate API key button. When you regenerate your API key, the old key becomes invalid and any requests made using the old key will be rejected. This can be beneficial in case your API key is compromised or you need to revoke access for any reason. Please be aware that the API key is common for all the functions, and that regenerating the key will reflect in all the functions. After regenerating the key, make sure to update any applications that use the old key with the new key to ensure that they continue to function properly.
  • Note that only admin users have access to the Regenerate API Key option.

Part 3: Create a Webhook in Zendesk:

  1. Go to Admin > Extension > HTTP Target.
  2. Provide the following information:
    • Function URL
    • Method - GET or POST
    • Select Content-type as JSON. To know more, click here.

Note:

  • The Function URL is the API Key URL which you get from Step 2.

Part 4: Create a Trigger in Zendesk:

  1. Condition - when a ticket is created.
  2. Notify Target - HTTP Target name

JSON Body of arguments:

{"arguments":
{
"requestBody":{

"details":{
"ticket":
{
"title":"{{ticket.title}}",
"description":"{{ticket.description}}",
"source":"{{ticket.via}}",
"priority":"{{ticket.priority}}",
"due_date":"{{ticket.due_date}}",
"URI":"{{ticket.url}}",
"status":"{{ticket.status}}"
},
"assigne":
{
"email":"{{ticket.assignee.email}}",
"name":"{{ticket.assignee.name}}",
"first_name":"{{ticket.assignee.first_name}}",
"last_name":"{{ticket.assignee.last_name}}"
},
"user":
{
"full_name":"{{current_user.name}}",
"first_name":"{{current_user.first_name}}",
"language":"{{current_user.language}}",
"details":"{{current_user.details}}",
"mobile":"{{current_user.phone}}",
"email":"{{current_user.email}}",
"organization":
{
"details":"{{current_user.organization.details}}",
"name":"{{current_user.organization.name}}"
}}
}}
}}

Part 5: Configure an argument which contains the entire request body.

When a webhook sends data to a function, there is no way of knowing the number of arguments present in it. In order to handle this issue, you can have the function contain the entire request body within a single argument.

Invoke the Desk API inside the Function and save the function.

The Outcome:

Creating a ticket in Zendesk:

Ticket is created in Zoho Desk