> For the complete documentation index, see [llms.txt](https://docs.sharelogic.com/unifi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sharelogic.com/unifi/4.6/integration-guides/freshservice/freshservice-knowledge-template-polling.md).

# Freshservice Knowledge Template (Polling)

This guide explains how to use the Freshservice Knowledge Polling Template.

{% hint style="info" %}
For access to this template please contact us.
{% endhint %}

## Overview

The Freshservice Article Poller template acts as a **starting point** for building a **one-way knowledge integration** between **ServiceNow** and **Freshservice**. The template works by polling Freshservice and synchronising knowledge content into ServiceNow using **Unifi**.

{% hint style="warning" %}
This document and accompanying template are provided for general use only. Information may be incomplete, outdated, or inaccurate. No responsibility or liability is accepted for any use or reliance on its contents. Users should review and verify all information independently.
{% endhint %}

<table data-header-hidden data-search="false"><thead><tr><th>Item</th><th>Value</th></tr></thead><tbody><tr><td><strong>Source System</strong></td><td>Freshservice</td></tr><tr><td><strong>Target System</strong></td><td>ServiceNow</td></tr><tr><td><strong>Direction</strong></td><td>Fresh -> ServiceNow</td></tr><tr><td><strong>Source Record</strong></td><td><code>article</code></td></tr><tr><td><strong>Target Record</strong></td><td><code>kb_knowledge</code></td></tr><tr><td><strong>Inbound sync method</strong></td><td>Polling</td></tr><tr><td><strong>Target API</strong></td><td>Freshservice API v2</td></tr><tr><td><strong>Template Version</strong></td><td>1.0.0</td></tr></tbody></table>

### Freshservice API

Freshworks has a range of API's to interact with their services; this template focuses on articles and the supporting file structure, which closely resembles the ServiceNow Knowledge structure.

* Getting articles may be achieved with the **View Solution Article** or **View List Of Solution Article** endpoints. Viewing a solution article gives some extra details, such as tags on the article.
  * [View Solution Article](https://api.freshservice.com/#view_solution_article): `GET /api/v2/solutions/articles/{id}`
  * [View List Of Solution Article](https://api.freshservice.com/#view_all_solution_article): `GET /api/v2/solutions/articles`
* Getting the file structure uses nested pollers to pull **categories**, **folders** and **subfolders**.
  * [View List of Solution Categories](https://api.freshservice.com/#view_all_solution_category): `GET /api/v2/solutions/categories`
  * [View Solution Folders](https://api.freshservice.com/#view_all_solution_folder): `GET /api/v2/solutions/folders`
  * [View Solution Sub Folders](https://api.freshservice.com/#view_solution_article): `GET /api/v2/solutions/folders/{id}/sub-folders`
* Getting attachments is handled by the **Download Attachment** endpoint for standard attachments and a \`**GET**\` to the link given for embedded attachments (Provided they are on Freshservice.com).
  * [Download Attachment](https://api.freshservice.com/#download_attachment): `GET /api/v2/attachments/[id]`
  * Embedded Attachment: `GET [region]attachment.freshservice.com/inline/attachment?token=[jwt_token]`

### Features

* Inbound creation and updating of knowledge articles.
* Attachment sync:
  * Full inbound sync.
  * Attachments and inline attachments are saved to ServiceNow.
  * Inline attachment references are updated to display the attachment stored on ServiceNow.

#### **Limitations**

* There is **no API** to **get only updated articles**, so polling **checks all folders**. This means it has a **high overhead**, so **should not be set to run** often enough **for near real-time sync** (though in practice this is not needed, as articles are likely not updated that frequently).
* **Approvals/publishing process** has **not** been **implemented**.
* **Access controls** and **updating users** have **not** been **synced**.

### Pre-requisites

* Access to a Freshservice instance.
  * Including a user with the **API-key** option **enabled**.
* A ServiceNow development instance with Unifi installed.

## Implementation

The process to make a new integration from the template is as follows.

### Usage

1. **Import** and make a **new integration from** the **template**.
2. **Setup** a **connection** between the two systems.
3. **Add** a **`u_correlation_id`** string field to **`kb_category`** and **`kb_knowledge`** tables.
4. **Trigger** the '**Get Categories**' poller; this will sync all folders and check them for articles and sync the articles.
5. **Review** [**Configuration Notes**](#configuration-notes) to decide on changes needed to adapt the integration to your instance.
6. **Customise** the **template** for your use case.

### Make a new integration from the Template

**Import the integration**; for guidance, see the following: [Import the Integration (external instance)](https://docs.sharelogic.com/unifi/~/changes/25/integration-guides/bidirectional-asynchronous-incident-guide/build-the-other-half/move-the-integration#import-the-integration-external-instance)

Once imported **open Unifi** and **navigate to the template** and **select** it, the option to create a **new integration from** the **template** will appear.

**Name** the new integration and '**Create**'. This will duplicate all components of the integration and change their sys\_id’s.

### Connection Setup

Two connections will need to be created, one connection to the customer's Freshservice sandbox and another to production. Within each connection enter the following details:

**Details**

* **Environment:** Sandbox or Production
* **Direction:** Bidirectional

**Outbound**

* **Endpoint URL:** `http://{customers-test-or-prod}.freshservice.com`
* **Authentication:** Basic
* **User:** `{Your-API-Key}`
* **Password:** `X`

**Inbound**

* **Inbound User:** `{Select user created in next section}`

#### **Account Setup**

Integration users need to be created on Freshservice and ServiceNow, these are the user accounts the API uses to make changes on their respective systems.

**ServiceNow User (Inbound user)**\
An inbound user is required for the integration to make updates. For this we **create a ServiceNow user with the** [**`x_snd_eb.integration`**](https://docs.sharelogic.com/unifi/about/roles) **role**. All integrations within the same process share the same endpoint, so when data is sent inbound, the inbound user is used to identify which integration to target, requiring a unique user per integration in the process. **This user should then be set on the connection**.

**Freshservice User**\
To connect to Freshservice we need an account with the ‘**API Key**’ option **enabled**. Documentation on finding this account's key is here: [How To Find Your API Key | Freshworks](https://crmsupport.freshworks.com/support/solutions/articles/215517-how-to-find-your-api-key). **Add this key into the connection** as shown in the connection section above. **This user should only be used on the integration**, as their actions are filtered out of synchronisation to prevent looping.

#### **Connection Variables**

Connection variables are key-value pairs which allow us to use different data values for different connections. We have used them to store values relevant to the template. You will need to update them to values relevant to your Fresh integrations.

The following updates need to be made:

* **`kb_knowledge_base`** The ServiceNow sys\_id of the knowledge base to which  `kb_category` and `kb_knowledge` articles should be synced.

## Configuration Notes

Configuration notes are given as an overview of what exists in the integration and can be used to help understand where changes should be made to alter functionality.

### Field maps

The following field maps exist in the integration.

<table><thead><tr><th width="234.99993896484375">Fields Map</th><th>Usage</th></tr></thead><tbody><tr><td>Choice (Integer)</td><td>Map choice field values to another value on in/outbound.<br>Freshdesk expects integers in the format "Property" : 2 rather than "Property":"2" as with the non-int version of this map.<br>Note: Choice options will be found using the parent choice field even when inheritance is disabled.</td></tr><tr><td>DateTime_FD</td><td>Convert a GlideDate/DateTime to and from an ISO 8601 date string.</td></tr><tr><td>Default Value</td><td>Send the default value set for this field.</td></tr><tr><td>Description (HTML)</td><td>Field for handling the description from Freshdesk.<br>Creates an array of inline attachments and replaces html that doesn't work on ServiceNow(Embedded code).</td></tr><tr><td>External Reference</td><td>Sets external_reference for Freshservice (ticket id) and stores it in a field.</td></tr><tr><td>Inbound Attachment Processor</td><td>Builds an <code>attachments</code> array from attachments on the payload.<br>If an array of <code>attachments</code> or <code>embeddedAttachment</code> exists on stage attempt to poll those attachments if they don't already exist on the bond.<br>If they do, replace embedded attachment links with the attachment URL on ServiceNow.</td></tr><tr><td>Reference correlation_id</td><td>Lookup and set a reference value by it's correlation_id.</td></tr><tr><td>String</td><td>Standard Field Map for String values</td></tr><tr><td>Tags</td><td>Given an array of tag will make sure tags on the record match the array.<br>Some issue with this field breaks in source to stage.</td></tr></tbody></table>

### Messages

The following messages exist in the integration.

#### **Inbound**

| Message       | Trigger(Freshservice/Pollers)                             | Functionality                      |
| ------------- | --------------------------------------------------------- | ---------------------------------- |
| AddAttachment | Pollers send a polled attachment into the integration.    | Logs attachments added by pollers. |
| CreateArticle | Poller finds a ticket with an Article that is not bonded. | Create the Article in ServiceNow.  |
| UpdateArticle | Poller detects a bonded Tickets has been updated.         | Update the Article.                |

#### **Suggestions**

When configuring an integration in Unifi we would normally suggest one message for each state change rather than just having one general `Update` message. This makes it easier to configure states with default fields like approver. It also makes it easier for an end user /analyst to understand where in the process things may have errored when debugging. For this integration, if you wish to configure approvals and other parts of the publishing process make a copy of this message and configure transitions based on the inbound fields.

### Poll Processors

#### **Get Article Poll Processor**

The '**Get Article**' poll processor has been configured to **pass through the whole article body** into Unifi so that there will be **no need to update the poll processor even if the object itself is updated**.&#x20;

It also **determines which message an inbound ticket should trigger** by querying the bond. **If more messages are introduced** to give granular control over the article publishing process **this will need to be updated** to determine the message to call.

#### **Other Poll Processors Containing Message Names**

The following poll processors contain message names and **will also need to be updated if message names change**.

| Poll Processor | Message names                   |
| -------------- | ------------------------------- |
| Get Attachment | `AddAttachment`                 |
| Get Article    | `CreateArticle`/`UpdateArticle` |

## Conclusion

With the above guidance, you should be able to configure a Freshservice Article Poller integration in Unifi. If you encounter any difficulties, please reach out to support, and we would be happy to help.

***

## Change History

| Version | Date       | Changes          |
| ------- | ---------- | ---------------- |
| 1.0.0   | 2026-08-20 | Initial template |
