> For the complete documentation index, see [llms.txt](https://docs.appmixer.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.appmixer.com/connector-configuration/servicenow.md).

# ServiceNow

### **Setup the App administrator account**

**App admin url**: <https://developer.servicenow.com/dev.do#!/home>

Once the app admin account is created and verified you need to create an instance.

<figure><img src="https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-fc7247d3ba556f3a4080f681987af49f9b26488b%2Fservicenow-1.png?alt=media" alt=""><figcaption></figcaption></figure>

It will take a minute ~~or two~~ ~~or three~~ or five to complete.

<figure><img src="https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-135eb25520852906d83563735b329567261843a8%2Fservicenow-2.png?alt=media" alt=""><figcaption></figcaption></figure>

Now your developer instance is ready and accessible: <https://dev180380.service-now.com/>. Note that when creating a new account, your instance ID (`dev180380` in this case) will be different.

### Setup Webhooks

To configure webhooks in ServiceNow to receive notifications when a new record is created, follow these steps. This involves creating an Outbound REST Message, setting up a Business Rule to capture record creation, and configuring the webhook.

#### Choose a Webhook Secret

Since connector version 4.0.0 the triggers (*New Record*, *Updated Record*, *Deleted Record*) only receive events that carry the connection's **Webhook Secret**.

* Generate a random string of at least 16 characters, for example with `openssl rand -base64 24`.
* Enter it in the **Webhook Secret** field when you connect the ServiceNow account in Appmixer. The triggers refuse to start without it.
* Send the same value in the `X-Appmixer-Secret` header of every event (see the REST Message below).

Appmixer delivers an event only to the flows whose connection has the same instance and the same Webhook Secret. Requests without the header are rejected with `401`. Events with a different secret or for another instance don't trigger any flow.

{% hint style="warning" %}
**Upgrading from a connector version before 4.0.0:** running trigger flows stop receiving events until you reconnect the ServiceNow account with a Webhook Secret and add the `X-Appmixer-Secret` header to the REST Message.
{% endhint %}

#### Create an Outbound REST Message

* Navigate to **System Web Services > Outbound > REST Message**.
* Click on the **New** button to create a new REST Message.
* Fill in the fields such as:
  * Name: e.g., `AppmixerNotifications`.
  * Endpoint: `https://<YOUR_API_BASE>/plugins/appmixer/servicenow/events` for example `https://api.appmixer.com/plugins/appmixer/servicenow/events`
* Click **Submit** and then open the newly created REST Message.
* Click on the **HTTP Methods** tab and create a new HTTP Method.
* Fill in the details such as:
  * Name: e.g., `events`.
  * HTTP Method: `POST`.
  * Endpoint: Ensure this is filled with your webhook listener’s URL.
* Add these HTTP Request Headers:
  * `Content-Type`: `application/json`
  * `X-Appmixer-Secret`: the Webhook Secret of your ServiceNow connection in Appmixer (required since connector version 4.0.0).
* Save the HTTP Method.

![Outbound REST](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-fea7ee70fd1019429131f42228da738b3acfa323%2Fservicenow_2.png?alt=media)

#### Create a Business Rule

* Navigate to the table for which you want to capture new record creation. For example, if it’s the Incident table, go to **Incident > All**.
* Right-click on the form header and select **Configure > Business Rules**.
* Alternatively, you can navigate to **Activity Subscriptions -> Administration -> Business Rules**.
* Click on the **New** button to create a new Business Rule.
  * Set the fields as follows:
  * Name: e.g., `Appmixer incident events`. Don't edit the built-in `incident events` rule, create a new one.
  * Table: Select the appropriate table (e.g., `Incident`).
  * When: `after`, `Insert`, `Update`, `Delete`. This setting will trigger an event in Appmixer whenever a record is inserted, updated, or deleted in the table. ![Business Rule](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-1d7783fb92db4a948b86618281e81b34eb8107d0%2Fservicenow_1.png?alt=media)
* Under **Advanced**, check the box **Advanced** to open the script editor.

> You need to be a user with admin permissions to perform this step.

* In the Script section, add the following code. Business rules in the global scope run as ES5, so the script uses `var`: `let` and `const` stop it from compiling, and the rule then silently does nothing. Please note that `AppmixerNotifications` must match the name of the Outbound REST Message specified in the previous step, and `events` should correspond to the event name defined in the Outbound REST Message.

  ```js
  (function executeRule(current, previous /*null when async*/) {

      function serializeGlideRecordToJSON(gr) {
          var obj = {};
          var fields = gr.getFields();

          for (var i = 0; i < fields.size(); i++) {
              var field = fields.get(i);
              var fieldName = field.getName();

              // skipping sensitive fields if necessary
              if (fieldName !== 'sys_updated_on' && fieldName !== 'sys_created_on') {
                  obj[fieldName] = gr.getValue(fieldName);
              }
          }

          // getFields() does not return sys_id; the triggers output it as the record ID
          obj.sys_id = gr.getUniqueValue();

          return obj;
      }

      var operation = current.operation();
      
      // Uncomment this line for tracing
      // messages can be seen in System Logs > System Log > All
      //gs.info("Webhook Rule Fired for " + gs.getProperty('instance_name'));

      var instance = gs.getProperty('instance_name');
      var tableName = current.getTableName();
      
      // Make sure this matches the name of your Outbound REST Message
      // `AppmixerNotifications` is the name of the Outbound REST Message
      // `events` is the name of the HTTP method within the `AppmixerNotifications` REST Message mapped to the Appmixer plugin url  
      var rq = new sn_ws.RESTMessageV2('AppmixerNotifications', 'events');
      var requestBody = {
          'type': instance + '.' + tableName + '.' + operation,
          'data': serializeGlideRecordToJSON(current)
      };

      rq.setRequestBody(JSON.stringify(requestBody));
      rq.execute();

  })(current, previous);    
  ```

#### Debug

To see messages triggered by the Business Rule go **System Logs > System Log > All**

![Log Message Screenshot](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-7896724ea5fc0921a7499ab28ade15e986b9e745%2Fservicenow_5.png?alt=media)

To see messages triggered by the `sn_ws.RESTMessageV2` within the Business Rule, go to **System Logs > Outbound HTTP Requests**

![Log Message Screenshot](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-ba7576ca2658b45630f08ee844611b944d5fcc6b%2Fservicenow_6.png?alt=media)

The Appmixer endpoint answers:

* `200`: the event was accepted. Only flows whose connection has the same instance and Webhook Secret are triggered.
* `401` (`Missing X-Appmixer-Secret header.`): the REST Message does not send the `X-Appmixer-Secret` header.
* `400` (`Missing 'type' property.`): the request body has no `type`.

If the request succeeds but no flow is triggered, check that the header value matches the Webhook Secret of the connection used by the trigger, and that the instance name in `type` matches the connection's instance.

### Username and Password Authentication

ServiceNow instances can restrict Basic authentication for APIs. With the restriction on, the REST API rejects a correct username and password with `401` unless the user has the **`snc_basic_auth_api_access`** role. If connecting the account with a username and password fails, add this role to the user (**User Administration > Users**, open the user, **Roles** tab, **Edit**), or use an API key (see below).

### Setup API Key

Follow steps on: <https://www.servicenow.com/docs/bundle/zurich-platform-security/page/integrate/authentication/task/configure-api-key.html>

After that is done, you should have:

1. Created **Inbound Authentication Profile**
2. Created **REST API Key**
3. Created **REST API Access Policy**

Main requirements in the set up:

* **Inbound Authentication Profile**

The *Auth Parameter* should be set to Type: **Auth Header** (Parameter Name: **x-sn-apikey**)

![Inbound Authentication Profile](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-2c747229e32d4ecd57d2479af7231cd8b9c50200%2Fservicenow_7.png?alt=media)

* **REST API Access Policy**

1. All checkboxes except for *Global* and *Apply to all versions* should be checked
2. The **Inbound authentication profile** table should have these two Authentication profiles:
   1. *API Key*
   2. *On-call subscription basic authentication*

![REST API Access Policy](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-547a8906a035210b0fd78591507d1cea552bd33c%2Fservicenow_8.png?alt=media)

The names of the authentication profiles can vary if you called them differently during their creation, the main point is that this REST API Access Policy should work with both API Key **AND** Basic Authentication otherwise you will receive error 401.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.appmixer.com/connector-configuration/servicenow.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
