# ServiceNow CMDB Integration Setup Guide

Sync Configuration Item data from ServiceNow's CMDB into PagerDuty's Enrichment Service

The ServiceNow CMDB integration automatically syncs Configuration Item (CI) data from your ServiceNow instance to PagerDuty's Enrichment Service. This creates enrichment **data tables** that enable you to enrich incoming PagerDuty events with contextual information from your ServiceNow CMDB. Read more about event enrichment in the [Event Enrichment documentation](/integrations/event-enrichment).

## How It Works

1. **Configure CMDB Tables** — Define which ServiceNow CMDB tables to sync (for example, `cmdb_ci_server`, `cmdb_ci_ip_switch`).
2. **Map Fields** — Specify which ServiceNow fields to use for matching events and which fields provide enrichment data.
3. **Sync Data** — Enable synchronization to automatically keep enrichment data up-to-date.
4. **Enrich Events** — Use the synced data in Event Enrichment rules to add context to alerts.

Each CMDB table configuration creates a corresponding enrichment schema that acts as a queryable **data table** for event enrichment.

> **Prerequisites:** - ServiceNow instance with API access enabled
>   - ServiceNow user account with read permissions for CMDB tables
>   - PagerDuty account with Event Enrichment enabled
>   - API authentication token

## Step 1: Create ServiceNow Integration

Create your integration with at least one CMDB table configuration. Credentials are added separately in Step 2.

### Request

```text
curl -X POST "https://api.pagerduty.com/enrichment/integrations/servicenow" \
  -H "Authorization: Token token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production CMDB Integration",
    "description": "Enrichment data from production ServiceNow instance",
    "cmdb_tables": [
      {
        "display_name": "Network Switches",
        "ci_table_name": "cmdb_ci_ip_switch",
        "query_filter": "operational_status=1",
        "field_mappings": [
          {
            "servicenow_field": "name",
            "event_field": "source"
          },
          {
            "servicenow_field": "operational_status",
            "event_field": "Operational Status"
          },
          {
            "servicenow_field": "support_group",
            "event_field": "Support Group"
          },
          {
            "servicenow_field": "u_platform",
            "event_field": "Platform"
          },
          {
            "servicenow_field": "sys_class_name",
            "event_field": "CI Class"
          }
        ]
      }
    ]
  }'
```

### Response: `201 Created`

```json
{
  "integration": {
    "id": "AGOACUG45VYBRJ6ZCGTBQFN5S4",
    "name": "Production CMDB Integration",
    "description": "Enrichment data from production ServiceNow instance",
    "cmdb_tables": [
      {
        "id": "AGOACUG5DR2ETBH5HBXUPP7KVI",
        "display_name": "Network Switches",
        "ci_table_name": "cmdb_ci_ip_switch",
        "query_filter": "operational_status=1",
        "field_mappings": [
          {
            "servicenow_field": "name",
            "event_field": "source"
          },
          {
            "servicenow_field": "operational_status",
            "event_field": "Operational Status"
          },
          {
            "servicenow_field": "support_group",
            "event_field": "Support Group"
          },
          {
            "servicenow_field": "u_platform",
            "event_field": "Platform"
          },
          {
            "servicenow_field": "sys_class_name",
            "event_field": "CI Class"
          }
        ],
        "status": "disabled",
        "created_at": "2026-01-27T21:16:43Z",
        "updated_at": "2026-01-27T21:16:43Z",
        "deleted_at": null
      }
    ],
    "credentials": null,
    "created_at": "2026-01-27T21:16:43Z",
    "updated_at": "2026-01-27T21:16:43Z"
  }
}
```

### Understanding Table Status

Each CMDB table has a `status` field indicating the current state of data synchronization:

- **disabled**: Data sync is not enabled (default for newly created tables).
- **syncing**: Initial sync in progress, data is being loaded from ServiceNow.
- **active**: Sync is healthy and incremental updates are running.
- **error**: Sync failed with an error (check credentials or table configuration).

Tables are created with `status: "disabled"` by default. You must explicitly enable sync (see Step 6) to begin data synchronization.

### Understanding Field Mappings

Field mappings define how ServiceNow CMDB data maps to PagerDuty event fields:

- `servicenow_field`: The column name in your ServiceNow CMDB table.
- `event_field`: The field name that appears in enriched PagerDuty events.

At least one field mapping is required. Typically, you map one ServiceNow field (like `name` or `sys_id`) to a query field in your events (like `source` or `host`), and additional ServiceNow fields to provide enrichment context.

### Query Filters

The optional `query_filter` parameter allows you to limit which CIs are synced from ServiceNow using ServiceNow's query syntax:

#### Examples

Syncs only CIs with operational status = 1 (operational):

```text
operational_status=1
```

Syncs only CIs where the custom field `u_deployment_status` is not null:

```text
u_deployment_status!=NULL
```

Syncs CIs belonging to "Database Team" and with category "Production" (use ^ for AND conditions):

```text
support_group=Database Team^category=Production
```

> **Note:** Query filters use ServiceNow's encoded query syntax. Test your filters in ServiceNow first to ensure they return the expected CIs.

### Dot-Walked Fields

ServiceNow allows you to traverse relationships using dot-walking syntax. This is useful when the enrichment data you need is in a related table.

#### Examples

This dot-walks from the CI to its support group, then to the group's manager, and finally retrieves the manager's email address.

```json
{
  "servicenow_field": "support_group.manager.email",
  "event_field": "Support Manager Email"
}
```

#### Common Dot-Walk Patterns

- `support_group.name` — Get the support group's display name.
- `location.city` — Get the CI's location city.
- `assigned_to.email` — Get the assigned user's email address.

## Step 2: Add ServiceNow Credentials

Add authentication credentials for your ServiceNow instance.

```text
curl -X POST "https://api.pagerduty.com/enrichment/integrations/servicenow/credentials" \
  -H "Authorization: Token token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "credentials": {
      "instance_endpoint": "https://your-instance.service-now.com",
      "user": "integration_user",
      "password": "YOUR_SERVICENOW_PASSWORD"
    }
  }'
```

### Response: `201 Created`

```json
{
  "credentials": {
    "id": "AGOCLRSKSB5OPMBBNIQC5X5R6E",
    "instance_endpoint": "https://your-instance.service-now.com",
    "user": "integration_user",
    "created_at": "2026-02-03T23:11:18Z",
    "updated_at": "2026-02-03T23:11:18Z",
    "deleted_at": null
  }
}
```

> **Important Notes:** - Passwords are never returned in API responses for security.
>   - Only **one credential set per account** is allowed.
>   - Credentials are shared across all ServiceNow integrations in your account.
>   - The ServiceNow user must have read access to the CMDB tables you configured.

## Step 3: Add Additional Tables (Optional)

You can add more CMDB tables to your integration (up to eight total per integration).

```text
curl -X POST "https://api.pagerduty.com/enrichment/integrations/servicenow/{integration_id}/tables" \
  -H "Authorization: Token token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cmdb_table": {
      "display_name": "Windows Servers",
      "ci_table_name": "cmdb_ci_win_server",
      "query_filter": null,
      "field_mappings": [
        {
          "servicenow_field": "name",
          "event_field": "source"
        },
        {
          "servicenow_field": "category",
          "event_field": "category"
        },
        {
          "servicenow_field": "fault_count",
          "event_field": "fault count"
        },
        {
          "servicenow_field": "cost_cc",
          "event_field": "cost cc"
        }
      ]
    }
  }'
```

### Response: `201 Created`

```json
{
  "cmdb_table": {
    "id": "AGOCLVITO53U7HIANUORTDCGRQ",
    "display_name": "Windows Servers",
    "ci_table_name": "cmdb_ci_win_server",
    "query_filter": null,
    "field_mappings": [
      {
        "servicenow_field": "name",
        "event_field": "source"
      },
      {
        "servicenow_field": "category",
        "event_field": "category"
      },
      {
        "servicenow_field": "fault_count",
        "event_field": "fault count"
      },
      {
        "servicenow_field": "cost_cc",
        "event_field": "cost cc"
      }
    ],
    "status": "disabled",
    "created_at": "2026-02-03T23:27:27Z",
    "updated_at": "2026-02-03T23:27:27Z",
    "deleted_at": null
  }
}
```

Each table you add creates a new enrichment schema that can be used independently in your Event Enrichment rules.

## Step 4: Update Table Configuration (Optional)

Modify field mappings, display names, or query filters for an existing table.

```text
curl -X PUT "https://api.pagerduty.com/enrichment/integrations/servicenow/{integration_id}/tables/{table_id}" \
  -H "Authorization: Token token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Production Network Switches",
    "query_filter": "operational_status=1^u_environment=production",
    "field_mappings": [
      {
        "servicenow_field": "name",
        "event_field": "source"
      },
      {
        "servicenow_field": "operational_status",
        "event_field": "Operational Status"
      },
      {
        "servicenow_field": "sys_class_name",
        "event_field": "CI Class"
      },
      {
        "servicenow_field": "support_group.name",
        "event_field": "Support Team"
      }
    ]
  }'
```

### Response: `200 OK`

(Returns updated table configuration.)

> **Note:** Table configurations cannot be modified once data sync has been enabled and the initial backfill has started.

Before enabling sync, you can update any aspect of the table configuration including the `ci_table_name`. However, changing the `ci_table_name` fundamentally changes which ServiceNow CMDB table is being synced, so if you need to sync a different table after enabling sync, you must create a new table configuration instead.

## Step 5: Test Table Configuration

Before enabling data sync, validate your configuration by testing it against live ServiceNow data. This endpoint queries ServiceNow and returns up to 10 sample records.

```text
curl -X GET "https://api.pagerduty.com/enrichment/integrations/servicenow/{integration_id}/tables/{table_id}/test" \
  -H "Authorization: Token token=YOUR_API_TOKEN"
```

### Response: `200 OK`

```json
{
  "enrichment_data": [
    {
      "sys_id": "27e3a47cc0a8000b001d28ab291fa65b",
      "sys_created_on": "2007-11-09 20:49:13",
      "name": "OWA-SD-01",
      "sys_updated_on": "2025-08-04 12:11:27",
      "category": "Do not migrate to asset",
      "fault_count": "0",
      "sys_class_name": "Windows Server",
      "cost_cc": "USD"
    },
    {
      "sys_id": "3a172e820a0a0bb40034228e9f65f1be",
      "sys_created_on": "2008-10-26 09:57:57",
      "name": "PS LoadBal01",
      "sys_updated_on": "2025-08-04 12:11:30",
      "category": "Do not migrate to asset",
      "fault_count": "0",
      "sys_class_name": "Windows Server",
      "cost_cc": "USD"
    },
    {
      "sys_id": "eb6e54539831f6500ebf0f2f73f452a4",
      "sys_created_on": "2025-12-18 13:24:13",
      "name": "prod-db-server-01",
      "sys_updated_on": "2025-12-18 13:30:01",
      "category": "Hardware",
      "fault_count": "0",
      "sys_class_name": "Windows Server",
      "cost_cc": "USD"
    }
  ]
}
```

### What This Validates

The test endpoint verifies:

-  Credentials are valid and authentication succeeds.
-  CMDB table exists and is accessible.
-  Query filter syntax is correct (if specified).
-  Mapped fields exist in the ServiceNow table.
-  Data is returned in the expected format.

> **Important:** The test response returns data using ServiceNow field names (not the `event_field` names you mapped). This helps you verify that you are mapping the correct ServiceNow fields.

### If the Test Fails, Check:

- ServiceNow credentials are correct.
- ServiceNow user has read permissions for the table.
- CMDB table name is spelled correctly.
- Query filter syntax is valid.
- All mapped ServiceNow fields exist in the table.

## Step 6: Enable Data Sync

Once you have tested your configuration, enable data synchronization to begin syncing CMDB data to PagerDuty.

```text
curl -X POST "https://api.pagerduty.com/enrichment/integrations/servicenow/{integration_id}/tables/{table_id}/enable" \
  -H "Authorization: Token token=YOUR_API_TOKEN"
```

### Response: `200 OK`

```json
{
  "table_id": "AGOACUG5DR2ETBH5HBXUPP7KVI",
  "sync_enabled": true,
  "message": "Data sync enabled successfully"
}
```

### After Enabling

- Data synchronization begins automatically.
- The enrichment schema is populated with CI data from ServiceNow.
- Data becomes available for use in Event Enrichment rules.
- Syncs occur periodically to keep data up-to-date.

### Disable Data Sync

To stop synchronization for a table:

```text
curl -X POST "https://api.pagerduty.com/enrichment/integrations/servicenow/{integration_id}/tables/{table_id}/disable" \
  -H "Authorization: Token token=YOUR_API_TOKEN"
```

### Response: `200 OK`

```json
{
  "table_id": "AGOACUG5DR2ETBH5HBXUPP7KVI",
  "sync_enabled": false,
  "message": "Data sync disabled successfully"
}
```

## View Integration Status

Retrieve your complete integration configuration including all tables, credentials, and current sync status for each table.

```text
curl -X GET "https://api.pagerduty.com/enrichment/integrations/servicenow/{integration_id}" \
  -H "Authorization: Token token=YOUR_API_TOKEN"
```

### Response: `200 OK`

```json
{
  "integration": {
    "id": "AGOACUG45VYBRJ6ZCGTBQFN5S4",
    "name": "Production CMDB Integration",
    "description": "Enrichment data from production ServiceNow instance",
    "cmdb_tables": [
      {
        "id": "AGOACUG5DR2ETBH5HBXUPP7KVI",
        "display_name": "Network Switches",
        "ci_table_name": "cmdb_ci_ip_switch",
        "query_filter": "operational_status=1",
        "field_mappings": [
          {
            "servicenow_field": "name",
            "event_field": "source"
          },
          {
            "servicenow_field": "operational_status",
            "event_field": "Operational Status"
          },
          {
            "servicenow_field": "support_group",
            "event_field": "Support Group"
          }
        ],
        "status": "active",
        "created_at": "2026-01-27T21:16:43Z",
        "updated_at": "2026-01-27T21:16:43Z",
        "deleted_at": null
      },
      {
        "id": "AGOCLVITO53U7HIANUORTDCGRQ",
        "display_name": "Windows Servers",
        "ci_table_name": "cmdb_ci_win_server",
        "query_filter": null,
        "field_mappings": [
          {
            "servicenow_field": "name",
            "event_field": "source"
          },
          {
            "servicenow_field": "category",
            "event_field": "category"
          }
        ],
        "status": "disabled",
        "created_at": "2026-02-03T23:27:27Z",
        "updated_at": "2026-02-03T23:27:27Z",
        "deleted_at": null
      }
    ],
    "credentials": {
      "id": "AGOCLRSKSB5OPMBBNIQC5X5R6E",
      "instance_endpoint": "https://your-instance.service-now.com",
      "user": "integration_user",
      "created_at": "2026-02-03T23:11:18Z",
      "updated_at": "2026-02-03T23:11:18Z",
      "deleted_at": null
    },
    "created_at": "2026-01-27T21:16:43Z",
    "updated_at": "2026-01-27T21:16:43Z"
  }
}
```

## Use ServiceNow Data In Event Enrichment

Once your tables are synced, you can use them in [Event Enrichment rules](/integrations/event-enrichment). The ServiceNow integration automatically creates enrichment schemas for each table configuration.

### Find Your Schemas

In the Event Enrichment rule editor:

1. Create or edit an Event Enrichment.
2. Add a new rule and select **Enrich events**.
3. In the **Join data from** dropdown, look for schemas with your configured display names:
   - "Network Switches"
   - "Windows Servers"

### Example Enrichment Rule

**Scenario**: Enrich events with support group information from your "Windows Servers" table.

#### Event Enrichment Rule Configuration

1. **Condition**: `event.custom_details.hostname` exists.
2. **Action**: Enrich events.
   1. **Join data from**: Windows Servers
   2. **Match on**: `event.custom_details.hostname` = source (the query field you mapped)
   3. **Write enrichment data to**: `event.custom_details.cmdb_info`

When an event comes in with a matching hostname, it will be enriched with category, fault count, and cost center data from ServiceNow.

## Advanced Configuration

### Specify Query Fields

By default, the integration automatically uses the `name` field as the query field — the field used to match incoming PagerDuty events to CI records in ServiceNow. This works well for most setups where events carry the CI name.

If your events use a different identifier (like `sys_id`, `ip_address`, or a custom field), or if you want to match on multiple fields simultaneously, you can explicitly designate which fields to use as query fields by adding `"type": "query"` to those field mappings.

#### Default Behavior (Auto-Detect)

When no `type` is specified on any field mapping, `name` is automatically used as the query field. All other fields provide enrichment context. This is the recommended approach for most integrations.

```json
{
  "field_mappings": [
    { "servicenow_field": "name",              "event_field": "host" },
    { "servicenow_field": "support_group",     "event_field": "Support Group" },
    { "servicenow_field": "operational_status","event_field": "Operational Status" }
  ]
}
```

#### Explicit Query Field

Set `"type": "query"` on any field to use it as the query field instead of `name`. In this mode, `name` is not required and is treated as a regular enrichment field if included.

```json
{
  "field_mappings": [
    { "servicenow_field": "sys_id",            "event_field": "ci_id",           "type": "query" },
    { "servicenow_field": "name",              "event_field": "host" },
    { "servicenow_field": "support_group",     "event_field": "Support Group" },
    { "servicenow_field": "operational_status","event_field": "Operational Status" }
  ]
}
```

Here, CI records are looked up by `sys_id` rather than `name`. Events must carry the `ci_id` field with a matching value.

#### Multiple Query Fields

You can designate up to three fields as query fields. When multiple query fields are configured, all of them must be present in the event for a match to occur. This is useful when a single field is not unique enough to identify a CI.

```json
{
  "field_mappings": [
    { "servicenow_field": "name",           "event_field": "host",     "type": "query" },
    { "servicenow_field": "sys_class_name", "event_field": "ci_class", "type": "query" },
    { "servicenow_field": "support_group",  "event_field": "Support Group" },
    { "servicenow_field": "location",       "event_field": "Location" }
  ]
}
```

In this example, a CI is only matched if the event contains both a matching `host` and a matching `ci_class`.

#### View Field Types in Responses

The integration API always returns a `type` field on each field mapping in responses, showing how each field is configured (`query` or `enriched`).

#### Constraints

- At most three fields may have `"type": "query"`.
- At least one field must be an enrichment field (no `type` specified).
- Only `query` is a valid value for `type` on requests — any other value is rejected.

## Product Limits

- **1 ServiceNow integration** per account.
- **Up to 5 CMDB tables** per integration.
- **2-20 field mappings** per table.
- **1 credential set** per account (shared across integrations).

## Troubleshooting

### Integration Creation Fails

**Error**: `Account already has a ServiceNow integration`

- Only one ServiceNow integration is allowed per account.
- Delete the existing integration or add tables to it instead.

**Error**: `Invalid CMDB table name`

- Verify the table exists in your ServiceNow instance.
- Check spelling and capitalization (table names are case-sensitive).
- Ensure the ServiceNow user has access to the table.

### Credential Issues

**Error**: `Authentication failed`

- Verify the ServiceNow instance URL is correct (include `https://`).
- Check that username and password are correct.
- Ensure the ServiceNow user account is active and not locked.

**Error**: `Insufficient permissions`

- ServiceNow user must have read access to configured CMDB tables.
- Check role assignments in ServiceNow (typically requires itil or admin role).

### Test Endpoint Failures

**Returns empty array**:

- Query filter may be too restrictive (no records match).
- Test the query filter in ServiceNow first to verify results.
- Try testing without a query filter to confirm table access.

**Error on specific fields**:

- Field name may be misspelled or not exist in the table.
- Check the ServiceNow table dictionary for correct field names.
- For dot-walked fields, verify the relationship exists.

### Sync Issues

**Data not appearing in enrichment**:

- Verify sync is enabled for the table (check the integration status endpoint).
- Allow time for initial sync to complete (may take several hours for large tables).
- Check that credentials are still valid.

**Data is stale**:

- Syncs occur periodically (approximately once per hour).
- Consider updating query filters if specific records are not syncing.
- Verify ServiceNow data has actually changed.

## Next Steps

After setting up your ServiceNow integration:

1. **[Create Event Enrichment rules](/integrations/event-enrichment)** using your synced CMDB data.
2. **Test enrichment** by sending sample events with matching query field values.
3. **Monitor sync status** to ensure data stays current.
4. **Add more tables** as needed for different CI types or teams.
