External Events

Events that occur in an external product or a third-party service are termed as external events. You can enable external events to trigger apps. To do this:

  1. Generate a target URL - link to where the app receives webhook data.
  2. Create a webhook in the external product or service, to subscribe to external events. When creating a webhook specify the target URL for the webhook to send data.
  3. Configure event listeners in the manifest.json file.

When an external event occurs, the webhook uses the target URL, notifies the app about the external event, and sends data to the app. The configured event listener invokes a callback method. The app logic in the callback method defined in server.js, runs with the help of the event-specific payload passed to the callback method.

Sample Use Cases

  • Proactive Support: You want to create a ticket in Frehservice when a certain event occurs (e.g. a payment in Stripe fails).
  • Data Sync: You want to make the same change in the corresponding Frehservice contact when a contact is created or modified in an external product.
  • Real-time Updates: You want to notify the agent to whom a ticket is assigned when a JIRA issue that has been linked to a Frehservice ticket is closed. You can even send a reply to the ticket requester.

Note:
1. The rate limit for external events is 250 triggers per minute.
2. The app execution timeout is 20 seconds.
3. The serverless environment supports webhook data (incoming content) whose content type is one of the following:
- application/json
- application/xml
- text/xml
- application/x-www-form-urlencoded

Take a look at JIRA events Freshdesk app for a demonstration of this feature.

onAppInstall - Webhook Registration

To generate a webhook URL when an app is installed and use the URL to register the webhook:

  1. From the app’s root directory, navigate to the server.js file.
  2. In the callback method associated with the onAppInstall event,
    1. Include the generateTargetUrl() method. The webhook URL generated is unique for each app installation.
    2. Include an API request to the external product, for webhook registration. In the API request, ensure to specify the authorization mechanism (Basic) and the JSON object that the external product requires to successfully register the webhook.

      Notes:
      1. The generateTargetUrl() method is supported only in onAppInstall() and product event callbacks.
      2. You can register multiple webhooks in this callback method.

  3. When a webhook is successfully registered, the external product sends a webhook id. This webhook id can be used to deregister the webhook, when the app is uninstalled. In the callback method, include a mechanism to store the webhook id.

Sample manifest.json Copied Copy
1
2
3
4
5
"events": { "onAppInstall": { "handler": "onAppInstallCallback" } }
EXPAND ↓

Sample server.js Copied Copy
1
2
3
4
5
6
7
8
9
10
11
exports = { onAppInstallHandler: function(payload) { generateTargetUrl() .then(function(url) { //Include API call to the third party to register your webhook }, function(err) { // Handle error }); } };
EXPAND ↓

onExternalEvent - Configure Event

To register an external event and the corresponding callback:

  1. From your app’s root directory, navigate to the manifest.json file.
  2. Include the events attribute, specifying the external event and the corresponding callback methods as follows:
    Copied Copy
    1
    2
    3
    4
    5
    6
    7
    8
    "events": [ "onAppInstall": { "handler": "onAppInstallHandler" }, "onExternalEvent": { "handler": "onExternalEventHandler" } ]
    EXPAND ↓

    Note: Include only one callback method for an event.

  3. Navigate to the server.js file.
  4. In the exports block, enter the callback function definition as follows:
    Copied Copy
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    exports = { onAppInstallHandler: function(payload) { generateTargetUrl() .then(function(url) { //API call to the external product to register the webhook. }) .fail(function(err) { // Handle error }); }, onExternalEventHandler: function(payload) { //This is the callback function definition. //Include the logic to perform any action in Freshservice. console.log("Logging arguments from the event:" + JSON.stringify(payload)); if(payload.data.thirdpartyissue.id = 3) { //your code to perform action within freshservice } } }
    EXPAND ↓

Payload Attributes

When an external event occurs, the external product passes an event-specific payload as webhook data to the target URL (app framework). This data is passed as payload to the external event’s callback method.

Payload structure Copied Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
{ "account_id" : "value", "event" : "value", "region" : "value", "timestamp" : "value", "domain" : "value", "headers" : {}, "data" : {}, "iparams" : { "Param1" : "value", "Param2" : "value" } }
EXPAND ↓

Attribute Type Description
account_id number Freshservice account ID.
event string Name of the event (onExternalEvent).
region string Region where the Freshservice account is deployed.
Possible values: US, EU, EUC, AUS, and IND.
timestamp number Time (epoch format) the event was received.
domain string Freshservice account domain.
headers object Webhook headers.
data object Webhook payload, the size should not exceed 128 KB.
iparams object Installation Parameters.

Sample payload

Copied Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{ "account_id": 12345, "event": "onExternalEvent", "timestamp" : 1496400354326, "region" : "US", "domain": "xyz.freshservice.com", "data": { "id": 2, "timestamp": "2009-09-09T00:08:36.796-0500", "issue": { "expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog", "id":"99291", "self":"https://jira.atlassian.com/rest/api/2/issue/99291", "key":"JRA-20002", "fields":{ "summary":"I feel the need for speed", "created":"2009-12-16T23:46:10.612-0600", "description":"Make the issue nav load 10x faster", "labels":["UI", "dialogue", "move"], "priority": "Minor" } }, "changelog": { "items": [ { "toString": "A new summary.", "to": null, "fromString": "What is going on here?????", "from": null, "fieldtype": "jira", "field": "summary" } ], "webhookEvent": "jira:issue_updated" } }, "headers": { "Content-Type": "application/json" }, "iparams": { } }
EXPAND ↓
onAppUninstall - Webhook Deregistration

To automatically deregister a webhook, when an app is uninstalled:

  1. From the app’s root directory, navigate to the server.js file.
  2. In the callback method associated with the onAppUninstall event,
    1. Include the mechanism to retrieve the webhook id saved during app installation.
    2. Include an API request to the external product, for webhook deregistration.
  3. Sample server.js file Copied Copy
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    exports = { onAppInstallHandler: function(payload) { generateTargetUrl() .then(function(url) { //API call to the external product to register the webhook. }) .fail(function(err) { // Handle error }); }, onExternalEventHandler: function(payload) { //This is the callback function definition. //Include the logic to perform any action in Freshservice. console.log("Logging arguments from the event:" + JSON.stringify(payload)); }, onAppUninstallHandler: function(payload) { //Include API call to the external product to deregister the webhook } }
    EXPAND ↓
  4. Navigate to the manifest.json file.
  5. In the events attribute, specify the external event and the corresponding callback methods.

    Sample manifest.json file

    Copied Copy
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    "events": [ "onAppInstall": { "handler": "onAppInstallHandler" }, "onExternalEvent": { "handler": "onExternalEventHandler" }, "onAppUninstall": { "handler": "onAppUninstallHandler" } ]
    EXPAND ↓

Testing

Note: For testing, we recommend that you use the latest version of Chrome browser.

You can easily test your app in your machine by simulating events. Also, you can test different scenarios by directly modifying the payload.

Note:
As the testing is only a simulation of events, an actual event will not be recorded in the back end. If you need an actual ticket/contact to be created, then it is recommended that you publish your app as a custom app and test the operation manually.

To simulate events for local testing, follow the given procedure.

  1. In your console, navigate to your project directory, and execute the following command. $ fdk run
  2. Open your browser and enter the following URL to start testing your app: http://localhost:10001/web/test.
  3. Select the event that you want to simulate.
  4. Once you select an event, the corresponding event payload is displayed. Edit the values and click Simulate. When you edit the payload, ensure that you adhere to the JSON format.
  5. If the event is successfully simulated, you will see Success displayed.
  6. If there is a problem, you will see Failed displayed. Check if the payload is valid and then resume testing.

Testing with ngrok

The Freshworks Development Kit (FDK) uses the node module ngrok to create secure tunnels between your local FDK instance and ngrok cloud. According to ngrok.io, ngrok exposes local servers behind NATs and firewalls to the Internet over secure tunnels. The FDK leverages this feature to expose its webhook to third-party services to test external events app integrations.

To test external events on your computer using ngrok,

  1. Run the following command: $ fdk run --tunnel

    Note: If you have ngrok authorization privileges, run the following command: fdk run --tunnel --tunnel-auth <auth-key>

  2. The following message is displayed.
  3. In your browser, enter the following URL: http://localhost:10001/web/test
  4. From the drop-down list, select the OnAppInstall event to proceed with webhook registration.

Once the webhook is registered, go to a third-party service from where your app must receive external events and trigger an event. The event payload will be received in the app as an argument to the external event.