> For the complete documentation index, see [llms.txt](https://prohelp.assetpanda.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://prohelp.assetpanda.com/integrations-store/ticket-management/servicenow-integration/servicenow-setup-guide.md).

# ServiceNow Setup Guide

## ServiceNow terminology

<table><thead><tr><th width="219.890625" valign="top">Term</th><th valign="top">Description</th></tr></thead><tbody><tr><td valign="top">User</td><td valign="top">An account that can log into ServiceNow. You will create a special user that represents the Asset Panda Pro integration.</td></tr><tr><td valign="top">Role</td><td valign="top">A user label that is referenced when an Access Control List (ACL) checks for it.</td></tr><tr><td valign="top">ACL (Access Control List)</td><td valign="top">A rule that gives permission for a role to read/write a certain table or field.</td></tr><tr><td valign="top">Table</td><td valign="top">Where ServiceNow stores records. For example, the Incident table stores every incident ticket while the User table stores every person.</td></tr><tr><td valign="top">Field</td><td valign="top">A column within a table. For example, the Incident table includes fields such as Short description or Priority.</td></tr></tbody></table>

***

## Create the integration user

1. In the left navigation pane, click the search field and enter <kbd>Users</kbd>. Matching results are displayed.
2. Under **User Administration**, click **Users**. The Users page displays all user accounts on the ServiceNow instance.
3. Above the list, click **New**. The User - New record window is displayed.
4. For **User ID**, enter a short username (for example, adam).
5. Enter the **First name** and **Last name** for this account (for example: <kbd>Adam Miller</kbd>).
6. Enter an **Email address** for the account.
7. For **Identity type**, select **Machine** to identify that this account represents a system/integration, not a real person logging in.
8. Select **Internal Integration User** to confirm that the account is used only by another system calling in automatically.
9. Leave **Active** checked and leave **Locked out** unchecked.
10. Click **Submit**. The screen shows the saved user record and prompts you to set up the user's password.
11. Click **Set Password**, set a password, and confirm it.

{% hint style="info" %}
The password should be long and can letters, numbers, and simple symbols, such as - and\_ . Avoid & % ? = # — as these have special meaning in web addresses and can silently break the integration's login step.
{% endhint %}

***

## Create a custom role

1. In the left navigation pane, click the search field and enter <kbd>Roles</kbd>.
2. Under **User Administration**, click **Roles**. The page displays all roles on the instance.
3. Click **New**.
4. For **Name**, enter <kbd>integration\_assetpanda\_readonlyx</kbd> .
5. Enter a short **Description** (for example, <kbd>Read-only role for the Asset Panda integration</kbd>).
6. Leave **Elevated privilege** unchecked.
7. Click **Submit**.

***

## Temporarily enable security administration

ServiceNow hides the ability to create Access Control Lists (ACLs) from ordinary admin accounts. You must briefly elevate your session to unlock it. This does not change any settings permanently.

1. Click your profile picture/avatar icon and then select **Elevate Roles**. A popup displays the roles you are allowed to elevate to.
2. Select **security\_admin** and then click **OK**.

{% hint style="info" %}
If **Elevate Roles** is not displayed, your account does not have the security\_admin role. To add it, return to the Users view, open your user account and then add the role.
{% endhint %}

***

## Access Control (ACL) screen overview

All permissions you add are added in the ACL screen.

1. In the left navigation pane, click the search field and enter <kbd>Access Control</kbd>.
2. Under **System Security**, click **Access Control (ACL)**. The Access Controls list shows all existing permission rules on the instance.
3. Click **New**.

{% hint style="info" %}
If the **New** button is not available, ensure that you’ve temporarily assigned the System Administrator role.
{% endhint %}

4. Complete the following fields:

<table><thead><tr><th width="148" valign="top">Field</th><th width="222.73046875" valign="top">Setting</th><th valign="top">Notes</th></tr></thead><tbody><tr><td valign="top">Type</td><td valign="top">record</td><td valign="top">This permission refers to a piece of data.</td></tr><tr><td valign="top">Operation</td><td valign="top">read</td><td valign="top">Read permission prevents the changing, adding, or deleting of data.</td></tr><tr><td valign="top">Decision Type</td><td valign="top">Allow If</td><td valign="top">This rule grants access when its conditions are.</td></tr><tr><td valign="top">Name</td><td valign="top">Table name that you search for and select</td><td valign="top">Defines the table (for example, Asset, Incident, or User) this rule applies to.</td></tr><tr><td valign="top">Field</td><td valign="top">“-- None --” or one specific field</td><td valign="top"><p>Leave as None to cover the whole table.</p><p>Pick a specific field to cover just that one column.</p></td></tr><tr><td valign="top">Requires role</td><td valign="top">Your custom role</td><td valign="top"><p>Only users with this role have the configured access.</p><p>This setting is required.</p></td></tr></tbody></table>

***

## Give access to the data tables

The following permissions give the integration access to assets, incident tickets, and user accounts. Repeat these six actions for each table.

### Asset table

1. On the **Access Controls** list, click **New**.
2. Leave **Type** as **record**.
3. For **Operation**, select **read**.
4. Leave **Decision Type** as **Allow If**.
5. In the drop-down next to **Name**, enter <kbd>asset</kbd>.
6. From the results, click **Asset \[alm\_asset].**
7. Leave the second drop-down as **-- None --**.
8. Under **Requires role**, click **Insert a new row**.
9. Enter <kbd>integration\_assetpanda\_readonlyx</kbd> and click it when it appears below the box.
10. Click **Submit** at the top of the page. The page reloads and shows this information as a saved record.

### Incident table

Repeat the previous procedure with the following exceptions:

1. In the drop-down next to **Name**, enter <kbd>incident</kbd>.
2. From the results, click **Incident \[incident]**.

#### User table

Repeat the previous procedure with the following exceptions:

1. In the drop-down next to **Name**, enter <kbd>sys\_user</kbd>.
2. From the results, click **User \[sys\_user]**.

### Additional setup

Before Asset Panda Pro pulls any records, it asks ServiceNow the following questions about the Asset table:

* **“What other table does the Asset table build on top of?”**\
  This question is answered by the sys\_db\_object table, which is ServiceNow's internal directory listing every table that exists, and what each one is built from.
* **“What columns does the Asset table have, and what type is each one?”**\
  This question is answered by the sys\_dictionary table, which is ServiceNow's internal directory that lists every field on every table, along with details like its name, data type, and whether it is required.

The integration reads data from these directories before it accesses Asset, Incident, or User data.

These tables need their own read permissions, like Asset, Incident, and User. If these permissions are not set, the integration fail with a permissions error.

***

## Give access to sys\_db\_object

### Whole-table permission

1. In the navigation pane, enter <kbd>Access Control</kbd> and select **Access Control (ACL).**
2. Click **New**.
3. Leave **Type** as **record**.
4. Click **Operation** and choose **read**.
5. Leave **Decision Type** as **Allow If**.
6. In the drop-down next to **Name**, enter <kbd>sys\_db\_object</kbd> and then click Table **\[sys\_db\_object]**.
7. Leave the second drop-down as **-- None --**.
8. Under **Requires role**, click **Insert a new row**, enter <kbd>integration\_assetpanda\_readonlyx</kbd>, and select it.
9. Click **Submit**.

### Additional column permission: Extends table

Even with whole-table access granted, ServiceNow separately checks permission on individual columns before it allows a request. The integration asks sys\_db\_object for one column (super\_class) that records what a table is built from.

1. Click **New** to start a new permission record.
2. Leave **Type** as **record**.
3. Click **Operation** and choose **read**.
4. Leave **Decision Type** as **Allow If**.
5. In the drop-down next to **Name**, enter <kbd>sys\_db\_object</kbd> and then click **Table \[sys\_db\_object]**.
6. In the second drop-down, enter <kbd>extends</kbd>. One matching result appears: **Extends table**. This is the on-screen name for the super\_class column.
7. Click **Extends table**.
8. Under **Requires role**, click **Insert a new row**, enter <kbd>integration\_assetpanda\_readonlyx</kbd>, and select it.
9. Click **Submit**.

{% hint style="info" %}
The **Name** field looks for fields by their plain-English label. If a search for a name like super\_class, internal\_type, or default\_value comes back with No matches found, it means the label is worded differently. Try a plain guess, such as extends, type, or default, instead.
{% endhint %}

***

## Give access to sys\_dictionary

### Whole-table permission

1. From the **Access Control (ACL)** list, click **New**.
2. Leave **Type** as **record**.
3. Click **Operation** and choose **read**.
4. Leave **Decision Type** as **Allow If**.
5. In the drop-down next to **Name**, enter <kbd>sys\_dictionary</kbd> and then click **Dictionary Entry \[sys\_dictionary]**.

{% hint style="info" %}
Do not click **Dictionary Entry Override \[sys\_dictionary\_override]***.*
{% endhint %}

6. Leave the second drop-down as **-- None --**.
7. Under **Requires role**, click **Insert a new row**, enter <kbd>integration\_assetpanda\_readonlyx</kbd>, and select it.
8. Click **Submit**.

### Additional required column permissions

The sys\_dictionary table has additional stricter protection built into ServiceNow on several of its individual columns. The integration's request specifically lists eight columns it wants information about.

For every row in the following table, do the following:

1. Click **New** on the **Access Controls** list.
2. Leave **Type** as **record**.
3. Click **Operation** and choose **read**.
4. Leave **Decision Type** as **Allow If**.
5. In the drop-down next to **Name**, enter <kbd>sys\_dictionary</kbd> and then click **Dictionary Entry \[sys\_dictionary]**.
6. In the second drop-down, enter the search text from the table for that row, and then click the matching **Click** result.
7. Under **Requires** role, click **Insert a new row**, enter <kbd>integration\_assetpanda\_readonlyx</kbd>, and select it.
8. Click **Submit**.

<table><thead><tr><th width="182.7890625" valign="top">Internal computer name (for reference)</th><th width="142.265625" valign="top">Search Text</th><th valign="top">Click</th></tr></thead><tbody><tr><td valign="top">element</td><td valign="top">column name</td><td valign="top">Column name</td></tr><tr><td valign="top">column_label</td><td valign="top">column</td><td valign="top">Column label</td></tr><tr><td valign="top">internal_type</td><td valign="top">type</td><td valign="top"><p>Type</p><p>Do not click <strong>Calculation Type</strong> or <strong>Reference Type</strong>.</p></td></tr><tr><td valign="top">max_length</td><td valign="top">max length</td><td valign="top">Max length</td></tr><tr><td valign="top">mandatory</td><td valign="top">mandatory</td><td valign="top">Mandatory</td></tr><tr><td valign="top">reference</td><td valign="top">reference</td><td valign="top">Reference</td></tr><tr><td valign="top">choice</td><td valign="top">choice</td><td valign="top">Choice</td></tr><tr><td valign="top">default_value</td><td valign="top">default</td><td valign="top">Default value</td></tr></tbody></table>

### Additional column permissions

The integration uses two columns to decide which record to look at, rather than to display information from. They are never displayed in the results, but are used to filter/search. ServiceNow requires permission on these columns.

Repeat the previous procedure for the following columns:

<table><thead><tr><th width="199.1796875" valign="top">Internal computer name (for reference)</th><th width="118.69921875" valign="top">Search Text</th><th valign="top">Click</th></tr></thead><tbody><tr><td valign="top">name</td><td valign="top">table</td><td valign="top">Table — two similar options also appear: “Choice table” and “Table reference.” Do not pick those; pick the plain word Table by itself.</td></tr><tr><td valign="top">active</td><td valign="top">active</td><td valign="top">Active</td></tr></tbody></table>

***

## Verify all permissions

1. In the navigation pane, enter <kbd>Access Control</kbd> and select **Access Control (ACL)**.
2. For **Name**, enter <kbd>sys\_dictionary</kbd>. The permissions you created for that table are displayed.
3. Verify that one whole-table entry plus 10 column entries (11 total) are displayed. If the list does not show a **Field** column:
   1. Right-click any column title (like **Name** or **Operation**).
   2. Select **Configure > List Layout**.
   3. Select **Field** and then click the arrow to move it to the right.
   4. Click **Save**. Rows are displayed for each column for quick review.
4. Repeat the search-and-count check for the following tables:&#x20;
   * sys\_db\_object (one whole-table entry plus one entry for Extends table)
   * alm\_asset (one whole-table entry)
   * incident (one whole-table entry)
   * sys\_user (one whole-table entry)

***

## Assign the new role to the Integration User

1. &#x20;In the navigation pane, enter <kbd>Users</kbd>, and select **Users** under **User Administration**.
2. Select the integration user you created previously (for example, <kbd>adam</kbd>).
3. Click the **Roles** tab for the user and then click **Edit** on the displayed panel. Available and assigned roles are displayed.
4. In the search field above the **Available** list, enter <kbd>integration\_assetpanda\_readonlyx</kbd>
5. Click the matching role to highlight it, then click the right arrow to move the role to the right.
6. Click **Save**.
7. On the user's page, review the **Roles** list.

If any unintended roles are added, click the check box next to the role, then select **Actions on selected rows > Delete**.

***

## Register the OAuth application

You must register the OAuth application to define how Asset Panda Pro proves it is allowed to connect to the data.

1. In the navigation pane, enter <kbd>Inbound Integrations</kbd>.
2. Click the matching result (found under **Machine Identity Console**).
3. Click **New**. A question asks “What kind of OAuth application?” with clickable option&#x73;*.*
4. Click **New Inbound Integration Experience**. You are prompted to select an access method.
5. Click **OAuth - Resource Owner Password Credential Grant**. Asset Panda Pro will connect using the integration user's plain username and password, rather than someone clicking allow in a browser.
6. Enter a descriptive **Name** (for example, adam-integration).
7. For **Provider name**, select the most appropriate option. This label for ServiceNow's own records does not change how the connection works. ServiceNow generates a Client ID and Client Secret on this screen.
8. Click the small eye icon next to **Client secret** to reveal it. Copy the **Client ID** and Client **Secret** somewhere safe, such as a password manager. Do not leave them only visible on your screen, and never share a screenshot containing them.
9. Leave **Active** checked.
10. Set the **Auth scope** (recommended but optional):

    1. Under **Auth scope**, click **Create auth scope**. A note warns that a built-in option called useraccount grants access to everything the user could ever see. Do not choose this option.
    2. For **Name**, enter <kbd>assetpanda\_readonly\_scope</kbd> and click **Save**.
    3. On the main screen, ensure the new scope is selected under **Auth scope.**
    4. For **Limit authorization to the following APIs**, enter <kbd>table</kbd>.
    5. From the matching results, click **Table API**. Do not select **Table Batch API** or **Table Builder Application**.
    6. Make sure **Allow access only to APIs in selected scope** is checked.
    7. Click **Save**.

    This process ensures that the OAuth key cannot be used for anything beyond reading data, in case any previous permissions were set incorrectly.

***

## Test the integration

Perform the following tasks using a tool called curl (available by default on Mac and Linux terminals, and on Windows via PowerShell or the Command Prompt on recent versions).

### Ask ServiceNow for a temporary access token

`curl -X POST "https://<instance>.service-now.com/oauth_token.do" \   -d "grant_type=password" \   -d "client_id=<CLIENT_ID>" \   -d "client_secret=<CLIENT_SECRET>" \   -d "username=<integration_user>" \   -d "password=<PASSWORD>"`

Replace everything inside \<angle brackets> with your values from the previous procedures. If successful, ServiceNow replies with a block of text containing the access\_token.

### Use the token to read a record

`curl -X GET "https://<instance>.service-now.com/api/now/table/alm_asset?sysparm_limit=1" \   -H "Authorization: Bearer <ACCESS_TOKEN>"`

Replace \<ACCESS\_TOKEN> with the access\_token value from the previous task. If everything was set up correctly, ServiceNow replies with asset data instead of an error message.

Repeat the command, changing alm\_asset to incident, then to sys\_user, to confirm that all three work.

***

## Permission checklist

<table><thead><tr><th width="205.6015625" valign="top">Table</th><th width="135.1484375" valign="top">Field</th><th valign="top">Usage</th></tr></thead><tbody><tr><td valign="top">Asset [alm_asset]</td><td valign="top">-- None --</td><td valign="top">Read real asset records</td></tr><tr><td valign="top">Incident [incident]</td><td valign="top">-- None --</td><td valign="top">Read real incident records</td></tr><tr><td valign="top">User [sys_user]</td><td valign="top">-- None --</td><td valign="top">Read real user records</td></tr><tr><td valign="top">Table [sys_db_object]</td><td valign="top">-- None --</td><td valign="top">Look up a table's basic info</td></tr><tr><td valign="top">Table [sys_db_object]</td><td valign="top">Extends table</td><td valign="top">Look up what a table is built from</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">-- None --</td><td valign="top">Look up a table's columns, generally</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Column name</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Column label</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Type</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Max length</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Mandatory</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Reference</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Choice</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Default value</td><td valign="top">One specific column detail</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Table</td><td valign="top">Used to filter/search, not shown in results</td></tr><tr><td valign="top">Dictionary Entry [sys_dictionary]</td><td valign="top">Active</td><td valign="top">Used to filter/search, not shown in results</td></tr></tbody></table>

Every row must have **Operation** set to **read**, and <kbd>integration\_assetpanda\_readonlyx</kbd> added under **Requires role**.
