> ## Documentation Index
> Fetch the complete documentation index at: https://doc.lucidworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ServiceNow V1

> The ServiceNow V1 connector ingests records, knowledge articles, incidents, tasks, and other content from your ServiceNow instance into Fusion for search and analysis.

export const schema = {
  "type": "object",
  "title": "ServiceNow",
  "description": "Connects to a ServiceNow web service. This requires that OAuth has been enabled for the ServiceNow instance.",
  "required": ["id", "connector", "type", "pipeline", "properties"],
  "properties": {
    "category": {
      "type": "string",
      "title": "Category",
      "default": "Repository",
      "hints": ["hidden", "readonly"]
    },
    "id": {
      "type": "string",
      "title": "Datasource ID",
      "description": "Unique name for this datasource.",
      "minLength": 1,
      "pattern": "^[a-zA-Z0-9_-]+$"
    },
    "connector": {
      "type": "string",
      "title": "Connector Type",
      "description": "Connector Type.",
      "hints": ["hidden"],
      "minLength": 1
    },
    "type": {
      "type": "string",
      "title": "Datasource Type",
      "description": "Datasource type supported by the selected connector type.",
      "hints": ["hidden"],
      "minLength": 1
    },
    "pipeline": {
      "type": "string",
      "title": "Pipeline ID",
      "description": "Name of an existing index pipeline for processing documents.",
      "minLength": 1
    },
    "description": {
      "type": "string",
      "title": "Description",
      "description": "Optional description for this datasource."
    },
    "type_description": {
      "type": "string",
      "title": "Type Description",
      "default": "Connects to a ServiceNow web service. This requires that OAuth has been enabled for the ServiceNow instance.",
      "hints": ["hidden", "readonly"]
    },
    "properties": {
      "type": "object",
      "title": "Properties",
      "description": "Datasource configuration properties",
      "required": ["servicenow_instance_url", "servicenow_username", "servicenow_password", "oauth_application_client_id", "oauth_application_client_secret"],
      "properties": {
        "collection": {
          "type": "string",
          "title": "Collection",
          "description": "Collection documents will be indexed to.",
          "hints": ["hidden"],
          "pattern": "^[a-zA-Z0-9_-]+$"
        },
        "db": {
          "type": "object",
          "title": "Connector DB",
          "description": "Type and properties for a ConnectorDB implementation to use with this datasource.",
          "required": ["type"],
          "properties": {
            "type": {
              "type": "string",
              "title": "Implementation Class Name",
              "description": "Fully qualified class name of ConnectorDb implementation.",
              "default": "com.lucidworks.connectors.db.impl.MapDbConnectorDb",
              "minLength": 1
            },
            "inlinks": {
              "type": "boolean",
              "title": "Process Inlinks?",
              "description": "Keep track of incoming links. This negatively impacts performance and size of DB.",
              "default": false
            },
            "aliases": {
              "type": "boolean",
              "title": "Process Aliases?",
              "description": "Keep track of original URI-s that resolved to the current URI. This negatively impacts performance and size of DB.",
              "default": false
            },
            "inv_aliases": {
              "type": "boolean",
              "title": "Process Inverted Aliases?",
              "description": "Keep track of target URI-s that the current URI resolves to. This negatively impacts performance and size of DB.",
              "default": false
            }
          },
          "hints": ["hidden"]
        },
        "servicenow_instance_url": {
          "type": "string",
          "title": "ServiceNow Instance URL",
          "description": "The ServiceNow instance address.",
          "minLength": 1
        },
        "servicenow_username": {
          "type": "string",
          "title": "ServiceNow username",
          "description": "A user with access to all of the tables configured below. This user should also have access to related tables, as appropriate, in order to retrieve content referenced in other tables.",
          "minLength": 1
        },
        "servicenow_password": {
          "type": "string",
          "title": "ServiceNow password",
          "description": "Password to access the ServiceNow instance.",
          "hints": ["secret"],
          "minLength": 1
        },
        "oauth_application_client_id": {
          "type": "string",
          "title": "OAuth application Client Id",
          "description": "OAuth application Client ID. This ID is created after registering the OAuth endpoint for the ServiceNow instance.",
          "minLength": 1
        },
        "oauth_application_client_secret": {
          "type": "string",
          "title": "OAuth application Client Secret",
          "description": "OAuth application Client Secret. This key is created after registering the OAuth endpoint for the ServiceNow instance.",
          "hints": ["secret"],
          "minLength": 1
        },
        "enable_security_trimming": {
          "type": "boolean",
          "title": "Enable Security Trimming",
          "description": "Security trimming restricts query results to records the user is allowed to access by indexing user access information with other document metadata. Enable this option to index user access metadata.",
          "default": false
        },
        "tables_to_crawl": {
          "type": "array",
          "title": "ServiceNow tables to crawl",
          "description": "ServiceNow tables to fetch content from. At least one table name should be entered",
          "minItems": 1,
          "items": {
            "type": "string"
          }
        },
        "fields_to_crawl": {
          "type": "array",
          "title": "Fields to fetch per table",
          "description": "A list of fields to be fetched for each table. Leave empty to retrieve all fields.",
          "items": {
            "type": "string"
          }
        },
        "exclude_field_name_value": {
          "type": "array",
          "title": "Exclude records by field values",
          "description": "Records can be excluded based on values of specific fields. Enter exclusions in the format fieldName=fieldValue, e.g., workflow_state=review.",
          "items": {
            "type": "string"
          }
        },
        "batch_size": {
          "type": "integer",
          "title": "Batch size",
          "description": "Number of records to fetch in batch requests. The default is 100 to avoid the ServiceNow REST request timeout of 60 seconds. Only increase the batch size if you are sure a higher batch size will not trigger the timeout.",
          "default": 100,
          "hints": ["advanced"],
          "maximum": 10000,
          "exclusiveMaximum": false,
          "minimum": 1,
          "exclusiveMinimum": false
        },
        "diagnostic_mode": {
          "type": "boolean",
          "title": "Diagnostic Mode",
          "description": "Enable to print more detailed information to the logs about each request.",
          "default": false,
          "hints": ["advanced"]
        },
        "proxyType": {
          "type": "string",
          "title": "Proxy type",
          "description": "Type of proxy to use, if any. Allowed values are 'HTTP' and 'SOCKS'. Leave empty for no proxy.",
          "default": "HTTP",
          "hints": ["hidden"]
        },
        "proxyHost": {
          "type": "string",
          "title": "Proxy host",
          "description": "The address to use when connecting through the proxy."
        },
        "proxyPort": {
          "type": "integer",
          "title": "Proxy port",
          "description": "The port to use when connecting through the proxy. (HTTP or SOCKS)"
        },
        "initial_mapping": {
          "type": "object",
          "title": "Initial field mapping",
          "description": "Provides mapping of fields before documents are sent to an index pipeline.",
          "properties": {
            "skip": {
              "type": "boolean",
              "title": "Skip This Stage",
              "description": "Set to true to skip this stage.",
              "default": false,
              "hints": ["advanced"]
            },
            "label": {
              "type": "string",
              "title": "Label",
              "description": "A unique label for this stage.",
              "hints": ["advanced"],
              "maxLength": 255
            },
            "condition": {
              "type": "string",
              "title": "Condition",
              "description": "Define a conditional script that must result in true or false. This can be used to determine if the stage should process or not.",
              "hints": ["code", "code/javascript", "advanced"]
            },
            "reservedFieldsMappingAllowed": {
              "type": "boolean",
              "title": "Allow System Fields Mapping?",
              "default": false,
              "hints": ["advanced"]
            },
            "retentionMappings": {
              "type": "array",
              "title": "Field Retention",
              "description": "Fields that should be kept or deleted",
              "hints": ["advanced"],
              "items": {
                "type": "object",
                "required": ["field"],
                "properties": {
                  "field": {
                    "type": "string",
                    "title": "Field",
                    "description": "The name of the field to operate on.",
                    "hints": ["advanced"]
                  },
                  "operation": {
                    "type": "string",
                    "title": "Operation",
                    "description": "The type of operation to perform: keep (default) or delete",
                    "enum": ["keep", "delete"],
                    "default": "keep",
                    "hints": ["advanced"]
                  }
                }
              }
            },
            "updateMappings": {
              "type": "array",
              "title": "Field Value Updates",
              "description": "Values that should be added to or set on a field. When a value is added, any values previously on the field will be retained. When a value is set, any values previously on the field will be overwritten.",
              "hints": ["advanced"],
              "items": {
                "type": "object",
                "required": ["field", "value"],
                "properties": {
                  "field": {
                    "type": "string",
                    "title": "Field",
                    "description": "The name of the field to operate on.",
                    "hints": ["advanced"]
                  },
                  "value": {
                    "type": "string",
                    "title": "Value",
                    "description": "The value to add to or set on the field.",
                    "hints": ["advanced"]
                  },
                  "operation": {
                    "type": "string",
                    "title": "Operation",
                    "description": "The type of operation to perform: add (default) or set.",
                    "enum": ["add", "set"],
                    "default": "add",
                    "hints": ["advanced"]
                  }
                }
              }
            },
            "translationMappings": {
              "type": "array",
              "title": "Field Translations",
              "description": "Fields that should be moved or copied to another field. When a field is moved, the values from the source field are moved over to the target field and the source field is removed. When a field is copied, the values from the source field are copied over to the target field and the source field is retained.",
              "hints": ["advanced"],
              "items": {
                "type": "object",
                "required": ["source", "target"],
                "properties": {
                  "source": {
                    "type": "string",
                    "title": "Source Field",
                    "description": "The name of the field to operate on.",
                    "hints": ["advanced"]
                  },
                  "target": {
                    "type": "string",
                    "title": "Target Field",
                    "description": "The name of the target field.",
                    "hints": ["advanced"]
                  },
                  "operation": {
                    "type": "string",
                    "title": "Operation",
                    "description": "The type of operation to perform: copy (default) or move.",
                    "enum": ["copy", "move"],
                    "default": "copy",
                    "hints": ["advanced"]
                  }
                }
              }
            },
            "unmappedRule": {
              "type": "object",
              "title": "Unmapped Fields",
              "description": "Fields not mapped by the above rules. By default, any remaining fields will be kept on the document.",
              "properties": {
                "keep": {
                  "type": "boolean",
                  "title": "Keep",
                  "description": "Keep all unmapped fields",
                  "default": true,
                  "hints": ["advanced"]
                },
                "delete": {
                  "type": "boolean",
                  "title": "Delete",
                  "description": "Delete all unmapped fields",
                  "default": false,
                  "hints": ["advanced"]
                },
                "fieldToMoveValuesTo": {
                  "type": "string",
                  "title": "Move",
                  "description": "Move all unmapped field values to this field",
                  "hints": ["advanced"]
                },
                "fieldToCopyValuesTo": {
                  "type": "string",
                  "title": "Copy",
                  "description": "Copy all unmapped field values to this field",
                  "hints": ["advanced"]
                },
                "valueToAddToUnmappedFields": {
                  "type": "string",
                  "title": "Add",
                  "description": "Add this value to all unmapped fields",
                  "hints": ["advanced"]
                },
                "valueToSetOnUnmappedFields": {
                  "type": "string",
                  "title": "Set",
                  "description": "Set this value on all unmapped fields",
                  "hints": ["advanced"]
                }
              }
            }
          },
          "category": "Field Transformation",
          "categoryPriority": 7,
          "hints": ["advanced"],
          "unsafe": false
        }
      },
      "propertyGroups": [{
        "label": "Limit Documents",
        "properties": ["tables_to_crawl", "fields_to_crawl", "exclude_field_name_value"]
      }, {
        "label": "Crawl Performance",
        "properties": ["batch_size"]
      }, {
        "label": "Field Mapping",
        "properties": ["initial_mapping"]
      }]
    }
  },
  "category": "Other",
  "categoryPriority": 1,
  "unsafe": false
};

export const SchemaParamFields = ({schema}) => {
  const sanitize = str => {
    if (typeof str !== "string") return str;
    return str.replace(/^"(.*)"$/s, "$1").replace(/\\/g, "").replace(/"/g, "'");
  };
  const formatDescription = str => {
    const s = sanitize(str);
    return (/[.!?]\)*$/).test(s) ? s : `${s}.`;
  };
  const {description, properties = {}, required: requiredProps = []} = schema;
  const visibleProps = useMemo(() => Object.entries(properties).filter(([, prop]) => !prop.hints?.includes("hidden")), [properties]);
  return <div>
      {description && <p>{formatDescription(description)}</p>}

      {visibleProps.map(([name, prop]) => {
    const isRequired = requiredProps.includes(name);
    const hasDefault = prop.default !== undefined;
    const rawDefault = prop.default;
    const isComplexDefault = hasDefault && (typeof rawDefault === "object" || typeof rawDefault === "string" && (rawDefault.length > 20 || rawDefault.includes('"')));
    const fieldProps = {
      key: name,
      body: prop.title || name,
      type: prop.type,
      ...prop.title && ({
        post: [<><span className="text-stone-400 dark:text-stone-500">API property: </span>{name}</>]
      }),
      ...isRequired && ({
        required: true
      }),
      ...!isComplexDefault && hasDefault ? {
        default: sanitize(String(rawDefault))
      } : {}
    };
    const isObject = prop.type === "object" && prop.properties;
    const isArrayOfObjects = prop.type === "array" && prop.items?.type === "object" && prop.items.properties;
    return <ParamField {...fieldProps}>
            {prop.description && <p>{formatDescription(prop.description)}</p>}

            {isComplexDefault && <div className="flex">
                <p>
                  <strong>Default:</strong>
                </p>
                <pre className="!my-0">
                  <code>
                    {JSON.stringify(rawDefault, null, 2)}
                  </code>
                </pre>
              </div>}

            {isArrayOfObjects && <div className="flex">
              <p>
                <strong>Object attributes:</strong>
              </p>
              <pre className="!my-0">
                <code>
                  {'{\n'}
                  {Object.entries(prop.items.properties).map(([iname, iprop]) => <>
                      {`  ${iname}`}
                      {prop.items?.required?.includes(iname) && <span style={{
      color: 'red'
    }}> required</span>}
                      {`: {\n    display name: ${sanitize(iprop.title || '')}\n    type: ${iprop.type}\n  }\n`}
                    </>)}
                  {'}'}
                </code>
              </pre>
              </div>}

            {isObject && <Expandable title="properties">
                <SchemaParamFields schema={{
      properties: prop.properties,
      required: prop.required
    }} />
              </Expandable>}
          </ParamField>;
  })}
    </div>;
};

export const LwTemplate = ({title = "Key questions to get you started", icon = "sparkles", cta = "Powered by Agent Studio", linkHref = "https://lucidworks.com/demo/?utm_source=docs&utm_medium=referral&utm_campaign=docs_cta_ai"}) => {
  const [isLoaded, setIsLoaded] = useState(false);
  useEffect(() => {
    const timer = setTimeout(() => {
      setIsLoaded(true);
    }, 500);
    return () => clearTimeout(timer);
  }, []);
  return <div className="lw-template-container">
      <Card title={title} icon={icon}>
        {isLoaded && <span dangerouslySetInnerHTML={{
    __html: `<lw-template id="a029c1a9-28be-427e-b0e1-5d918920246a"></lw-template
            >`
  }} />}
        <Link href={linkHref} className="agent-studio-link text-left text-gray-600 gap-2 dark:text-gray-400 text-sm font-medium flex flex-row items-center hover:text-primary dark:hover:text-primary-light group-hover:text-primary group-hover:dark:text-primary-light">Powered by Lucidworks Agent Studio</Link>
      </Card>
    </div>;
};

[localhost link]: http://localhost:3000/docs/fusion-connectors/connectors/v1/servicenow

[mintlify link]: https://doc.lucidworks.com/docs/fusion-connectors/connectors/v1/servicenow

[old doc.lw link]: https://doc.lucidworks.com/fusion-connectors/44

<Callout icon="plug" color="#A4C6F7" iconType="solid">
  **Compatible with Fusion version:** 4.0.0 through 5.12.0
</Callout>

<Tip>
  V1 deprecation and removal notice

  All V1 connectors are deprecated in Fusion 5.18.0 and later. This means they are no longer being actively developed and will be removed in Fusion 6. V1 connectors were also previously deprecated in Fusion 5.12.0 but remained available in all versions between 5.12.0 and 5.18.0, including the Fusion 5.9.x long-term support release line, to support customers on those versions.

  The replacement for this connector is in active development at this time and will be released at a future date.

  If you are using this connector, you must migrate to the replacement connector or a supported alternative before upgrading to Fusion 6. Migrate to the replacement connector as soon as possible to avoid any disruption to your workflows.
</Tip>

<img src="https://mintcdn.com/lucidworks/Au994d8iJwF79HiU/assets/images/connectors/connector-api-flow-servicenow.png?fit=max&auto=format&n=Au994d8iJwF79HiU&q=85&s=ca72cdb0eebc29d4de04478b18bfeae4" alt="Connector flow" width="4157" height="1915" data-path="assets/images/connectors/connector-api-flow-servicenow.png" />

<LwTemplate />

## Prerequisites

Perform these prerequisites to ensure the connector can reliably access, crawl, and index your data.
Proper setup helps avoid configuration or permission errors, so use the following guidelines to keep your content available for discovery and search in Fusion.

ServiceNow access requires a user account with the appropriate permissions:

* Authentication using basic authentication with username and password. If using OAuth, set it up in ServiceNow’s Application Registry.
* Access to target tables such as `incident` or `kb_knowledge`.
* Read permissions on required fields.
* Allow REST API access with the following permissions:
  * `rest_api_explorer` needed for Table API.
  * `snc_platform_rest_api_access` if only granting access for specific instances.
  * `read` access.

Before using the connector, confirm the user can access the ServiceNow REST API using `curl -u USERNAME:PASSWORD "\https://company.service-now.com/api/now/table/incident?sysparm_limit=1"`. You should get a JSON response with a record.

## Authentication

Setting up the correct authentication according to your organization's data governance policies helps keep sensitive data secure while allowing authorized indexing.

ServiceNow uses OAuth 2.0 for the client credentials flow with token endpoint.

You will need the following in Fusion:

* ServiceNow Instance URL
* ServiceNow username
* ServiceNow password
* OAuth application Client ID
* OAuth application Client Secret

### Create a user account in ServiceNow

Make sure the account has the following:

1. API access with a recommended role of `rest_api_explorer`.
2. Read access to the desired tables, such as `kb_knowledge` or `incident`

### Register a new application in ServiceNow

1. Go to: **System OAuth > Application Registry**.
2. Click **New > Create an OAuth API endpoint for external clients** and fill in:
   1. Name
   2. Client ID (this can be auto-generated or custom)
   3. Client secret
   4. Redirect URI (this is not required in Fusion, so you can enter any URI)
3. Assign scopes:
   1. Ensure your client has scopes like `table.*.read` for the required tables.
4. Test access:

```bash wrap theme={"dark"}
curl -X POST "\https://INSTANCE_NAME.service-now.com/OAUTH_TOKEN.do" \
  -d "grant_type=CLIENT_CREDENTIALS&client_id=CLIENT_ID&client_secret= CLIENT_SECRET&redirect_uri=REDIRECT_URI"
```

## See also

* [ServiceNow REST API reference documentation](https://www.servicenow.com/docs/bundle/zurich-api-reference/page/build/applications/concept/api-rest.html)
* [ServiceNow Developer REST API specifications](https://developer.servicenow.com/dev.do#!/reference/api/orlando/rest/)

## Configuration

ServiceNow records are stored in named tables.

The account used to crawl needs to have the `personalize_dictionary` role in addition to READ access to the following System Tables:

* Crawl

  * sys\_dictionary
  * sys\_glide\_object
  * sys\_db\_object
* Recrawl

  * sys\_audit\_delete
* Sec trimming:

  * sys\_security\_acl\_role
  * sys\_group\_has\_role
  * sys\_user\_grmember
  * sys\_user\_has\_role

<Tip>
  When entering configuration values in the UI, use *unescaped* characters, such as `\t` for the tab character. When entering configuration values in the API, use *escaped* characters, such as `\\t` for the tab character.
</Tip>

<SchemaParamFields schema={schema} />
