ServiceNow Bi-Directional Sync

Bi-directional synchronization between Incidents and ServiceNow enables real-time incident updates across both systems. Changes made in either system automatically propagate to the other within seconds.

Overview

The bi-directional sync provides:

  • Real-time Updates: Changes sync within 5 seconds
  • Field Ownership: Control which system owns each field
  • Conflict Resolution: Automatic handling of simultaneous edits
  • Drift Detection: Periodic reconciliation to catch missed updates

Prerequisites

  • ServiceNow instance with admin access
  • API user with incident table permissions
  • Network connectivity between systems
  • Webhook endpoint accessible from ServiceNow

Configuration

Step 1: Create Integration

Use the CLI to create a new ServiceNow integration:

im integration configure \
  --name "Production ServiceNow" \
  --type servicenow \
  --org acme-corp \
  --base-url "https://your-instance.service-now.com" \
  --direction bidirectional \
  --username "api_user" \
  --password "your_password"

Or use the API:

curl -X POST http://localhost:8080/api/v1/integrations \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "acme-corp",
    "integration_type": "servicenow",
    "name": "Production ServiceNow",
    "base_url": "https://your-instance.service-now.com",
    "credentials": {
      "username": "api_user",
      "password": "your_password"
    },
    "sync_direction": "bidirectional",
    "enabled": true
  }'

Step 2: Configure Webhook in ServiceNow

  1. Navigate to System Definition > Business Rules in ServiceNow
  2. Create a new Business Rule for the incident table
  3. Set trigger conditions: after insert, update
  4. Add the following script:
(function executeRule(current, previous) {
  var payload = {
    sys_id: current.sys_id.toString(),
    number: current.number.toString(),
    short_description: current.short_description.toString(),
    state: current.state.toString(),
    priority: current.priority.toString(),
    impact: current.impact.toString(),
    assigned_to: current.assigned_to.getDisplayValue(),
    updated_on: current.sys_updated_on.toString()
  };

  var request = new sn_ws.RESTMessageV2();
  request.setEndpoint("https://your-incidents-server/api/v1/webhooks/{integration_id}");
  request.setHttpMethod("POST");
  request.setRequestHeader("Content-Type", "application/json");
  request.setRequestHeader("X-ServiceNow-Signature", generateSignature(JSON.stringify(payload)));
  request.setRequestBody(JSON.stringify(payload));
  request.execute();
})(current, previous);

Step 3: Configure Field Ownership

Set up field ownership rules to control which system is authoritative for each field:

# Platform owns severity and title
im integration field-ownership set prod-snow severity --owner platform --priority 10
im integration field-ownership set prod-snow title --owner platform --priority 10

# ServiceNow owns assignment and work notes
im integration field-ownership set prod-snow assigned_to --owner external --priority 5
im integration field-ownership set prod-snow work_notes --owner external --priority 5

Field Mapping

Incidents Field ServiceNow Field Default Owner
title short_description Platform
description description Platform
severity priority + impact Platform
status state Platform
assigned_to assigned_to External
work_notes work_notes External

Status Mapping

Incidents Status ServiceNow State
open New (1), In Progress (2)
mitigated On Hold (3), Pending (4)
resolved Resolved (6)
closed Closed (7)

Conflict Resolution

When simultaneous edits occur within 5 seconds, the configured resolution strategy is applied:

Last-Write-Wins (Default)

The most recent update takes precedence:

im integration configure prod-snow --conflict-strategy last-write-wins

Ownership-Priority

The system with higher ownership priority for the field wins:

im integration configure prod-snow --conflict-strategy ownership-priority

Manual Review

Conflicts are queued for manual resolution:

im integration configure prod-snow --conflict-strategy manual-review

# View pending conflicts
im conflict list --integration prod-snow

# Resolve a conflict
im conflict resolve conflict-123 --use-platform

Drift Detection

Run periodic reconciliation to detect and fix drift:

# Check for drift without making changes
im integration reconcile prod-snow --dry-run

# Auto-heal detected drift
im integration reconcile prod-snow --auto-heal

# View reconciliation history
im integration reconcile history prod-snow

Scheduled Reconciliation

Configure automatic drift detection via the API:

curl -X POST http://localhost:8080/api/v1/integrations/{id}/reconcile/schedule \
  -H "Content-Type: application/json" \
  -d '{
    "interval": "1h",
    "auto_heal": true,
    "enabled": true
  }'

Monitoring

View Sync Status

# Check integration health
im integration sync-status prod-snow

# View linked incidents
im integration links prod-snow --format table

Dead Letter Queue

Failed syncs are queued for retry:

# View failed entries
im integration dlq prod-snow

# Retry a failed entry
im integration dlq-retry prod-snow entry-123

# Discard permanently failed entry
im integration dlq-discard prod-snow entry-456

Testing

Test the integration connection:

im integration test prod-snow

Troubleshooting

Common Issues

Webhook not receiving events

  • Verify ServiceNow can reach your webhook endpoint
  • Check the business rule is active and correctly configured
  • Validate HMAC signature is being generated correctly

Sync delays

  • Check network latency between systems
  • Verify rate limiting is not being triggered
  • Review the outbox queue for backlog

Field not syncing

  • Confirm field ownership rules are configured
  • Check field mapping exists for the field
  • Verify the field is included in webhook payload

Debug Logging

Enable detailed sync logging:

export INCIDENTS_LOG_LEVEL=debug
export INCIDENTS_SYNC_TRACE=true