Send Alerts to ServiceNow

Configure Edge Delta to create ServiceNow incidents automatically when alerts are triggered using the Table API.

Overview

This guide demonstrates how to create incidents in ServiceNow automatically when EdgeDelta alerts are triggered. ServiceNow is a popular IT Service Management (ITSM) platform used for incident management and workflow automation.

Prerequisites

  1. ServiceNow Instance: Access to a ServiceNow instance (e.g., instance.service-now.com)
  2. ServiceNow Credentials: A user account with permissions to create incidents via the REST API
  3. Basic Authentication: Encode your credentials in Base64 format: username:password
  4. EdgeDelta Pipeline: A configured threshold node or monitor generating signals

Pipeline Flow

flowchart LR classDef icon-metrics fill:#E7EEFC,stroke:#2563EB,color:#0F2169; classDef icon-alert fill:#FDEAD7,stroke:#EA580C,color:#7C2D12; classDef icon-destination fill:#FCEADB,stroke:#EA580C,color:#7C2D12; classDef icon-service fill:#E9F5F4,stroke:#0F766E,color:#0F3B2E; Metrics["<span class='ph ph-chart-line-up'></span> Metric Source"] Threshold["<span class='ph ph-funnel'></span> Threshold Node"] Webhook["<span class='ph ph-paper-plane-tilt'></span> Webhook Destination"] ServiceNow["<span class='ph ph-ticket'></span> ServiceNow"] Metrics --> Threshold Threshold --> Webhook Webhook --> ServiceNow class Metrics icon-metrics; class Threshold icon-alert; class Webhook icon-destination; class ServiceNow icon-service;

Configuration

Step 1: Set up Environment Variables

Configure your ServiceNow credentials as environment variables on the EdgeDelta agent:

export SERVICENOW_INSTANCE="your-instance"
export SERVICENOW_CREDENTIALS="base64_encoded_username:password"

To encode credentials in Base64:

echo -n "username:password" | base64

Step 2: Create the Webhook Node

Configure a webhook node that sends alerts to ServiceNow’s Table API:

- name: servicenow_incidents
  type: webhook_output
  endpoint: https://${SERVICENOW_INSTANCE}.service-now.com/api/now/table/incident
  headers:
  - header: Content-Type
    value: "application/json"
  - header: Accept
    value: "application/json"
  - header: Authorization
    value: "Basic ${SERVICENOW_CREDENTIALS}"
  suppression_window: 30m
  payload: |
    {
      "short_description": "{{ .item.signal.title }}",
      "description": "EdgeDelta Alert Details:\n\nAlert: {{ .item.signal.description }}\n\nAffected System:\n- Host: {{ index .item.resource \"host.name\" }}\n- Source: {{ index .item.resource \"ed.source_name\" }}\n- Source Type: {{ index .item.resource \"ed.source_type\" }}\n\nMetric Information:\n- Metric Name: {{ .item.signal.name }}\n- Current Value: {{ .item.signal.value }}\n- Threshold: {{ .item.signal.threshold_value }}\n- Threshold Type: {{ .item.signal.threshold_type }}\n\nSignal ID: {{ .item.signal.signal_id }}\nTimestamp: {{ .item.timestamp }}",
      "urgency": "{{ if gt .item.signal.value .item.signal.threshold_value }}2{{ else }}3{{ end }}",
      "impact": "2",
      "category": "Infrastructure",
      "subcategory": "Monitoring",
      "assignment_group": "Infrastructure Team",
      "cmdb_ci": "{{ index .item.resource \"host.name\" }}",
      "correlation_id": "edgedelta-{{ .item.signal.signal_id }}",
      "work_notes": "Automated incident created by EdgeDelta monitoring at {{ .item.timestamp }}. Agent tag: {{ index .item.resource \"ed.tag\" }}"
    }    

Step 3: Connect to a Threshold Node

Connect this webhook node to a threshold node that triggers based on your monitoring criteria:

nodes:
  - name: error_rate_threshold
    type: threshold
    filter: item.name == "error_rate"
    condition: value > 0.05

  - name: servicenow_incidents
    type: webhook_output
    # ... configuration from above ...

links:
  - from: error_rate_threshold
    to: servicenow_incidents

Incident Payload Reference

The ServiceNow incident payload uses the following key fields:

FieldDescriptionEdgeDelta Variable
short_descriptionBrief incident summary (required)Alert title
descriptionDetailed incident informationCombines multiple alert fields
urgencyHow quickly the incident needs attention (1-3)Dynamically set based on threshold
impactBusiness impact (1-3)Fixed or can be dynamic
categoryIncident categoryFixed as “Infrastructure”
subcategoryMore specific categorizationFixed as “Monitoring”
assignment_groupTeam responsible for resolutionConfigure per your organization
cmdb_ciConfiguration item (affected server/service)Uses host name
correlation_idUnique identifier for deduplicationUses signal ID with prefix
work_notesInternal notes visible to IT staffAutomated creation context

Dynamic Priority Mapping

Map EdgeDelta alert severity to ServiceNow priority based on how far the metric exceeds its threshold:

payload: |
  {
    "priority": "{{ if gt .item.signal.value (mul .item.signal.threshold_value 2) }}1{{ else if gt .item.signal.value .item.signal.threshold_value }}2{{ else }}3{{ end }}",
    ...
  }  

Priority mapping:

  • 1 (Critical): Value exceeds 2x the threshold
  • 2 (High): Value exceeds the threshold
  • 3 (Moderate): Standard priority

Including Custom Attributes

Include custom attributes from EdgeDelta in the incident. Custom fields in ServiceNow typically start with u_:

payload: |
  {
    "u_environment": "{{ index .item.attributes \"environment\" | default \"production\" }}",
    "u_application": "{{ index .item.attributes \"application\" | default \"unknown\" }}",
    "u_region": "{{ index .item.attributes \"region\" | default \"us-east-1\" }}",
    ...
  }  

Auto-Resolution

Create a separate webhook to automatically resolve incidents when metrics return to normal. This requires a monitor or threshold configuration that can detect recovery.

- name: servicenow_resolve
  type: webhook_output
  endpoint: https://${SERVICENOW_INSTANCE}.service-now.com/api/now/table/incident
  headers:
  - header: Content-Type
    value: "application/json"
  - header: Authorization
    value: "Basic ${SERVICENOW_CREDENTIALS}"
  payload: |
    {
      "correlation_id": "edgedelta-{{ .item.signal.signal_id }}",
      "state": "6",
      "close_code": "Solved (Permanently)",
      "close_notes": "Alert condition resolved automatically at {{ .item.timestamp }}"
    }    

Note: Auto-resolution requires matching the correlation_id from the original incident. The incident must exist and be in an open state for the update to succeed.

Assignment Routing

Route incidents to different teams based on the alert source:

payload: |
  {
    "assignment_group": "{{ if contains (index .item.resource \"ed.source_name\") \"database\" }}Database Team{{ else if contains (index .item.resource \"ed.source_name\") \"network\" }}Network Team{{ else }}Infrastructure Team{{ end }}",
    ...
  }  

Testing

Test with a Local Endpoint

Before connecting to ServiceNow, test your payload using a local HTTP server:

endpoint: http://localhost:8080/webhook-test

Verify JSON Syntax

Use the EdgeDelta UI to validate your configuration before deployment.

Check ServiceNow Response

Successful incident creation returns the created incident details:

{
  "result": {
    "sys_id": "abcd1234efgh5678ijkl9012mnop3456",
    "number": "INC0001234",
    "short_description": "High CPU Usage on prod-server-01",
    "state": "1",
    "correlation_id": "edgedelta-signal-abc123"
  }
}

Troubleshooting

IssueSolution
401 UnauthorizedVerify Base64 encoded credentials and check user permissions
400 Bad RequestCheck JSON syntax and required fields for your ServiceNow instance
403 ForbiddenUser lacks permission to create incidents via API
Field not found errorsCustom fields vary by ServiceNow configuration - check your instance’s incident table schema
No incident createdVerify suppression window isn’t preventing notifications
Duplicate incidentsUse consistent correlation_id values for deduplication

Common Field Validation Issues

ServiceNow validates field values against configured choices. Common issues include:

  • Invalid category/subcategory: Check available values in your instance
  • Unknown assignment_group: Verify the group name exists exactly as specified
  • Invalid urgency/impact values: Must be 1, 2, or 3

Best Practices

  1. Use correlation IDs: Prevent duplicate incidents with unique, prefixed signal IDs
  2. Set appropriate suppression: 30 minutes is typically good for infrastructure alerts
  3. Include context: Provide enough detail in descriptions for effective troubleshooting
  4. Test thoroughly: Always test with non-production endpoints first
  5. Monitor API limits: ServiceNow has rate limits - ensure your alert volume is appropriate
  6. Use environment variables: Never hardcode credentials in configurations
  7. Map to CMDB: Use cmdb_ci to link incidents to configuration items for better tracking

See Also