Skip to Content

Integrate with External System (Webhook)

Send data to external systems via REST API webhooks when records are created or updated (e.g., Slack, Teams, third-party systems).

Table: incident When: async
#integration #webhook #rest-api #external-system #async #insert #update #slack #teams

Script Code

JavaScript
1(function executeRule(current, previous /*null when async*/) {
2
3  try {
4    // Configuration: Define webhook settings
5    var webhookUrl = gs.getProperty('integration.webhook.url');  // Store URL in system property
6    var webhookEnabled = gs.getProperty('integration.webhook.enabled', 'false') === 'true';
7
8    if (!webhookEnabled || !webhookUrl) {
9      gs.info('Webhook integration disabled or URL not configured');
10      return;
11    }
12
13    // Define conditions for sending webhook
14    var shouldSendWebhook = false;
15
16    // Example 1: Send webhook for high-priority incidents
17    if (current.priority.toString() === '1') {  // Critical priority
18      shouldSendWebhook = true;
19    }
20
21    // Example 2: Send webhook when incident is resolved
22    if (current.state.changesTo('6')) {  // Resolved
23      shouldSendWebhook = true;
24    }
25
26    // Example 3: Send webhook for new incidents
27    if (current.isNewRecord()) {
28      shouldSendWebhook = true;
29    }
30
31    if (!shouldSendWebhook) {
32      return;
33    }
34
35    // Build payload
36    var payload = {
37      event_type: current.isNewRecord() ? 'incident.created' : 'incident.updated',
38      timestamp: new GlideDateTime().getValue(),
39      incident: {
40        sys_id: current.sys_id.toString(),
41        number: current.number.toString(),
42        short_description: current.short_description.toString(),
43        state: current.state.getDisplayValue(),
44        priority: current.priority.getDisplayValue(),
45        urgency: current.urgency.getDisplayValue(),
46        impact: current.impact.getDisplayValue(),
47        category: current.category.toString(),
48        assignment_group: current.assignment_group.getDisplayValue(),
49        assigned_to: current.assigned_to.getDisplayValue(),
50        caller: {
51          name: current.caller_id.getDisplayValue(),
52          email: current.caller_id.email.toString(),
53          phone: current.caller_id.phone.toString()
54        },
55        opened_at: current.opened_at.getDisplayValue(),
56        url: gs.getProperty('glide.servlet.uri') + 'incident.do?sys_id=' + current.sys_id
57      },
58      metadata: {
59        instance: gs.getProperty('instance_name'),
60        updated_by: gs.getUserName()
61      }
62    };
63
64    // Add change-specific data for updates
65    if (!current.isNewRecord() && previous) {
66      payload.changes = [];
67
68      var trackedFields = ['priority', 'state', 'assignment_group', 'assigned_to'];
69      trackedFields.forEach(function(field) {
70        if (current[field].changes()) {
71          payload.changes.push({
72            field: field,
73            old_value: previous[field].getDisplayValue(),
74            new_value: current[field].getDisplayValue()
75          });
76        }
77      });
78    }
79
80    // Create REST message
81    var request = new sn_ws.RESTMessageV2();
82    request.setEndpoint(webhookUrl);
83    request.setHttpMethod('POST');
84
85    // Set headers
86    request.setRequestHeader('Content-Type', 'application/json');
87    request.setRequestHeader('Accept', 'application/json');
88
89    // Add authentication if required
90    var apiKey = gs.getProperty('integration.webhook.api_key');
91    if (apiKey) {
92      request.setRequestHeader('Authorization', 'Bearer ' + apiKey);
93    }
94
95    // Set request body
96    request.setRequestBody(JSON.stringify(payload));
97
98    // Set timeout (30 seconds)
99    request.setHttpTimeout(30000);
100
101    // Execute request
102    var response = request.execute();
103    var statusCode = response.getStatusCode();
104    var responseBody = response.getBody();
105
106    // Log success
107    if (statusCode >= 200 && statusCode < 300) {
108      gs.info('Webhook sent successfully for incident ' + current.number +
109              ', status: ' + statusCode);
110
111      // Optional: Update custom field to track integration status
112      // current.u_webhook_sent = true;
113      // current.u_webhook_sent_at = new GlideDateTime();
114      // current.update();
115    } else {
116      gs.error('Webhook failed for incident ' + current.number +
117               ', status: ' + statusCode + ', response: ' + responseBody);
118    }
119
120  } catch (e) {
121    gs.error('Error sending webhook for incident ' + current.number + ': ' + e.message);
122  }
123
124})(current, previous);

How to Use

1. Create system properties for webhook configuration: - integration.webhook.url (URL of external webhook) - integration.webhook.enabled (true/false) - integration.webhook.api_key (optional authentication) 2. Create an async Business Rule on your table 3. Check "Insert" and/or "Update" checkboxes 4. Customize the payload structure for your integration 5. Test with a webhook testing service (e.g., webhook.site) first 6. Implement error handling and retry logic as needed 7. Monitor system logs for integration errors

Explore More Scripts

Browse our complete library of ServiceNow scripts

View All Scripts