> 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/integration-guides/freshservice/freshservice-incident-template-webhook.md).

# Freshservice Incident Template (Webhook)

## Overview

The Freshservice template acts as a starting point for building an integration between Unifi and Freshservice. This version of the template integrates ServiceNow Incident's with tickets on Freshservice. This integration works by sending data bi-directionally, using messages from Unifi and Webhooks in Freshservice.

{% 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>Source System</td><td>ServiceNow</td></tr><tr><td>Target System</td><td>Freshservice</td></tr><tr><td>Direction</td><td>Bidirectional</td></tr><tr><td>Source Record</td><td><code>incident</code></td></tr><tr><td>Target Record</td><td><code>Ticket</code></td></tr><tr><td>Inbound sync method</td><td>Webhooks</td></tr><tr><td>Target API</td><td>Freshservice API v2</td></tr><tr><td>Template Version</td><td>1.0.0</td></tr></tbody></table>

To understand the template's construction, it helps to have a baseline understanding of the Freshservice API:

### Freshservice API

Freshworks has a range of API's to interact with their services; this template focuses on tickets and notes as those combine to closely resemble the ServiceNow Task structure with journal fields being used as a stand-in for notes.

* Updating [tickets](https://developers.Freshservice.com/api/#tickets) `PUT /api/v2/tickets/[ticket_id]` allows for updating of state, assigned agent and other details.
* Creating [notes](https://developers.Freshservice.com/api/#conversations) on Freshservice requires a call to `POST /api/v2/tickets/[ticket_id]/notes`, so some state transitions where a single action is taken of ServiceNow lead to two events being sent to Freshservice, updating the ticket and creation of a note.

### Features

* Bidirectional creation, updating and closing of tickets.
* Attachment sending outbound.

#### Issues <a href="#issues" id="issues"></a>

For full details see: [#limitations](#limitations "mention")

* Automation in Fresh doesn't include an event for all updates, so some changes may not be captured.
* Freshservice automation doesn't allow filtering out updates made by the integration user. These are mitigated in the template, though they may cause unexpected changes.

### Pre-requisites  <a href="#warning" id="warning"></a>

* Access to a Freshservice instance.
  * Including a user with the API-key option enabled
  * Access to automation on that instance.
* (Optional) A custom field on Freshservice to store the ServiceNow incident number.
* A ServiceNow development instance with Unifi installed.

## Implementation

The following describes the templates configuration on ServiceNow and the steps to implement on Freshservice. Please review how this configuration should be translated to your own instance.

### Usage

1. Configure the integration in both systems.
2. Create a ticket/Incident that triggers the integration.
3. Make an update on the other system.
4. If this works set about customising the template for your use-case.

### ServiceNow configuration

To configure, open the integration's connection section and create a new connection, set direction to Bidirectional and 'Endpoint URL' to the URL of the target Freshservice instance, this will likely look like `https://CHANGEME.Freshservice.com`\
Next click on the connection and select outbound; here's where we configure outbound authentication, for testing we'll use basic. Select the authentication dropdown and select basic. A User and Password box will appear. For these enter your [Freshservice API key](https://crmsupport.freshworks.com/support/solutions/articles/215517-how-to-find-your-api-key) into the User section and enter 'X' into the password.

Setup an inbound user on ServiceNow for the integration to log-in through, this user will need the `x_snd_eb_integration` and `itil` roles. Select this user on the inbound section of the connection.

#### **New fields**

The following fields were added to ServiceNow for use in this integration. The only field currently in use is `u_correlation_id` on the `sys_user` table. The others will likely be needed if user groups are to be synced and if state mappings are changed from direct to an more complex mapping system.

| Field                                      | Table            | Type         | Reason                                                                                          |
| ------------------------------------------ | ---------------- | ------------ | ----------------------------------------------------------------------------------------------- |
| u\_correlation\_id                         | sys\_user        | String (100) | Connecting Freshservice and ServiceNow users.                                                   |
| <p>u\_correlation\_id<br>{Not used}</p>    | sys\_user\_group | String (100) | Connecting Freshservice and ServiceNow groups.                                                  |
| <p>u\_correlation\_state<br>{Not used}</p> | Incident         | String (32)  | States such as Wait 3rd party on Freshservice should open out ticket without re-opening theirs. |

#### **Choice Mapping**

Mappings between fields will need to be reviewed to see if they match your configuration. These used the `Choice_int_FD` field map as Freshservice expects values to be sent as integers (1,2,3) rather than strings containing integers ("1","2","3"). This field map looks for a mapping on the parent field map regardless of if inheritance is enabled. A special map was made for priority, as inbound updates to an Incidents priority involve updating both impact and urgency.

<table><thead><tr><th width="128.4000244140625">Field SN</th><th width="128">Field FD</th><th>Configuration</th></tr></thead><tbody><tr><td>contact_type</td><td>source</td><td>Field stores how the customer created the ticket, values on ServiceNow are different to Freshservice, so the mapping is a best guess and may vary by configuration.<br>This field is required for create messages on Freshservice, so it defaults to 2(Portal) as this is the Freshservice default.</td></tr><tr><td>priority</td><td>priority</td><td>Maps priority between Freshservice and ServiceNow.<br>- ServiceNow OOTB 1 is Critical, while on Freshservice it's 4.<br>- Freshservice sends the string value of priority (Low, Medium, High, Critical), but expects the integer values</td></tr><tr><td>state</td><td>status</td><td>State field maps between the system states on Freshservice an ServiceNow see the configuration below.</td></tr></tbody></table>

#### **State Mapping**

{% hint style="info" %}
On Hold states, inbound state from Freshservice sets the state and on hold reason. Outbound, however, 'Pending' is sent regardless of the On Hold reason.
{% endhint %}

<table><thead><tr><th>Freshservice Status</th><th width="96">Value</th><th>ServiceNow state</th><th width="96">SN value</th><th>On hold reason</th><th>Hold value</th></tr></thead><tbody><tr><td></td><td></td><td>New</td><td>1</td><td></td><td></td></tr><tr><td>Open</td><td>2</td><td>In Progress</td><td>2</td><td></td><td></td></tr><tr><td>Pending</td><td>3</td><td>On Hold</td><td>3</td><td>Awaiting Evidence</td><td>2</td></tr><tr><td>Waiting on Customer*</td><td></td><td>On Hold</td><td>3</td><td>Awaiting Caller</td><td>1</td></tr><tr><td>Waiting on Third Party*</td><td></td><td>On Hold</td><td>3</td><td>Awaiting Vendor</td><td>4</td></tr><tr><td>Resolved</td><td>4</td><td>Resolved</td><td>6</td><td></td><td></td></tr><tr><td>Closed</td><td>5</td><td>Closed</td><td>7</td><td></td><td></td></tr><tr><td>Deleted^</td><td></td><td>Cancelled</td><td>8</td><td></td><td></td></tr></tbody></table>

\* : State not listed in Freshservice docs but does exist on instance.\
^: This state isn't mapped and exists as a suggestion.

### Freshservice configuration

Freshservice may be configured to send data to ServiceNow using [Automations](https://crmsupport.freshworks.com/support/solutions/articles/132589-using-webhooks-in-automation-rules).\
If using webhooks, a custom header `X-SND-EB-Message-Name` may be used to select which Unifi message is triggered; otherwise, the Unifi Integration message identification script will be used. For details on the message bodies sent when configuring this template see the Message bodies section.

#### Configuration Variables

The following variables are used in the integration to set defaults and properties. They will need to be configured for the integration

| Key                        | Value                                                 | Usage                                                                                                                                                                                                               |
| -------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| default\_assignment\_group | *sys\_user\_group\_sys\_id1234*                       | Default assignment group to assign new Incidents created via the integration to.                                                                                                                                    |
| default\_contact           | {Freshservice:Unique\_external\_id}                   | Default contact sent to Freshservice if no contact is set on a Incident created in ServiceNow. This is sent in the field Unique\_external\_id. If in use a user should be set-up in Freshservice with a matching ID |
| default\_user              | {Freshservice:id}                                     | ID of the default user to update Freshservice tickets as.                                                                                                                                                           |
| send\_matched\_user        | true/false                                            | If true and the user making the update on ServiceNow has a u\_correlation\_id, the users id will be sent. See Feedback loop for why this may be set a false.                                                        |
| source\_tag                | `<span style="display:none">SOURCE:ServiceNow</span>` | Hidden text that can be filtered for in outbound notes senders to prevent it sending notes sent inbound by ServiceNow. See Feedback loop                                                                            |

#### **Message bodies**

The following message bodies were used in automations on Freshservice to send data to ServiceNow. This is just a guide and should be reviewed based on your data protection policies and requirements.

**Create, Update & state changes**

Message used:

* Create
* Update
* Pending
* WaitingOnCustomer
* WaitingThirdParty
* Resume
* Resolve
* ReOpen
* Close

```json
{
	"email": "{{ticket.contact.email}}",
	"name": "{{ticket.contact.name}}",
	"phone": "{{ticket.contact.phone}}",
	"priority": "{{ticket.priority}}",
	"source": "{{ticket.source}}",
	"status": "{{ticket.status}}",
	"due_by": "{{ticket.due_by_time}}",
	"subject": "{{ticket.subject}}",
	"description": "{{ticket.description}}",
	"id": "{{ticket.id}}"
}
```

**Comment**

```json
{
	"body": "{{ticket.latest_public_comment}}",
	"id": "{{ticket.id}}"
}
```

**Worknote**

```json
{
	"body": "{{ticket.latest_private_comment}}",
	"id": "{{ticket.id}}"
}
```

Log group or assignee changes:

```json
{
	"body": "Freshservice group or agent changed\nGroup: {{ticket.group.name}}\nAgent: {{ticket.agent.name}}",
	"id": "{{ticket.id}}",
}
```

## Limitations

### Feedback loop

Automations in Freshservice offer limited options to filter when to trigger. As a result updates sent by ServiceNow often cause an automation on Freshservice to Trigger. This then repeats the action on ServiceNow which recognises the event was done over the integration and prevents it causing looping. For updates to the Incident/Ticket this doesn't create issues, for Notes and comments it can lead to them being created twice.&#x20;

This is avoided by adding a `source_tag` onto the end of Comments and Work\_notes sent to Freshservice which adds a hidden text to this field. When the automations on Freshservice see the text in this tag they stop processing, preventing double note creation.\
A caveat of reflected updates is that the data sent outbound needs to be the same as the data that will be sent in the response so as not to overwrite data.

#### **Other solutions attempted**

To prevent feedback we looked into the following options, but at time of writing, all of them missed a required feature.

* Sending updates in with only one user and not sending updates made by that user in automations.
  * Automations can be triggered by only select users, but there isn't an option for all users except the selected.
* Filtering tickets on the ServiceNow side by the updating user.
  * This information is not available in Fresh automations to send outbound.

### Sending attachments from Freshservice

The integration may add attachments to the Freshservice ticket from ServiceNow but isn't configured the other way round. This is because attachments in Freshservice are sent as links to the attachment and don't send the attachment itself. The description field on ServiceNow is set to remove these links as they can't be set to clickable. While in journal fields these links are picked up and reformatted to be clickable in ServiceNow.

In the Polling case template these attachments may be captured using put requests. Additional guidance is given in 'Configuring Inbound attachments'.

### Missing features

The following features may be desirable depending on your configuration and may be added in future template versions. Only missing features where a ServiceNow feature matches a Freshservice one are noted. Some of these features will not be implemented as they would make the template harder to customise for general use.

* Attachments added to ticket are not sent to ServiceNow.
* Rejection of reflected messages on ServiceNow.
* Sending attachments in journal fields on ServiceNow.
* Cancelled on ServiceNow could be mapped to deleted on Fresh.
* Assignment\_group matching: Lookup inbound assignment groups and send a group outbound if it has a correlation id that may be matched with Freshservice.
* Changing hold state sent to Freshservice based on the on hold reason selected.

## Messages

### Outbound

All outbound messages are postfixed with \[Out] and are sent from ServiceNow to Freshservice.\
Messages Prefixed with 'Note' send a note with information about an update like a state change or details added.\
See the image below for an overview of when the different messages are sent based on the state in ServiceNow.

| Message          | Endpoint | Trigger(ServiceNow)                                   | Functionality                                                                                     | Freshservice state |
| ---------------- | -------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------ |
| Create           | Ticket   | An unbonded Incident is added to integration company. | Create the Ticket in Freshservice.                                                                | Open               |
| Update           | Ticket   | Incident updates that don't change state.             | Send the update to Freshservice. Updates basic ticket fields                                      | -                  |
| InProgress       | Ticket   | Incident moves from New to InProgress.                | Change state and sync basic ticket fields.                                                        | Open               |
| NoteAssignee     | Notes    | Assignee or group changes.                            | Inform Freshservice agents about assignment status on ServiceNow.                                 | -                  |
| OnHold           | Ticket   | Incident moves from Open to On Hold.                  | Change state and sync basic ticket fields.                                                        | Awaiting Info      |
| NoteHoldReason   | Notes    | On Hold reason is changed.                            | Inform Freshservice agents about hold reason on ServiceNow.                                       | Awaiting Info      |
| Resume           | Ticket   | Incident moved from Awaiting Info to Open.            | Change state and sync basic ticket fields.                                                        | Open               |
| Resolve          | Ticket   | Incident moves to Resolved.                           | Change state and sync basic ticket fields.                                                        | Resolved           |
| NoteResolution   | Notes    | Incident moves to Resolved.                           | Create a private note with ServiceNow's resolution information.                                   | Resolved           |
| RejectResolution | Ticket   | Incident moves from Resolved to Open.                 | Change state and sync basic ticket fields.                                                        | Open               |
| NoteCancellation | Notes    | Incident state changes to Cancelled.                  | Add a note to Freshservice that the Incident has been cancelled on ServiceNow and break the bond. | -                  |
| Close            | Ticket   | Incident moves to Closed.                             | Change state, sync basic ticket fields and close bond.                                            | Closed             |
| PrivateNote      | Notes    | Worknote added.                                       | Create the worknote as a private note on Freshservice.                                            | -                  |
| PublicNote       | Notes    | Comment added.                                        | Create the comment as a public note on Freshservice.                                              | -                  |
| AddAttachment    | Ticket   | Attachment is added to the Incident.                  | Add attachments to the ticket.                                                                    | -                  |

Transitions between incident states in ServiceNow are shown below.

<figure><img src="https://3662067745-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDk6VgKBXe6rYT8F9wuaY%2Fuploads%2FLcHu0ACvIQuCzwKaAdUr%2FIncident-state-transitions-1.png?alt=media&amp;token=f3999311-c265-4409-ada0-4e1955abb19b" alt=""><figcaption></figcaption></figure>

### Inbound

All outbound messages are postfixed with \[In] and are sent into ServiceNow from Freshservice.\
See the image below for an overview of when the different messages are sent based on the status in Freshservice.

| Message             | Trigger(Freshservice)                                                               | Functionality                                                   | ServiceNow State |
| ------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------- |
| Create              | Ticket meets condition for bonding with ServiceNow.                                 | Create the Incident in ServiceNow.                              | New              |
| Update              | Update is made to the ticket that doesn't change state.                             | Update the Incident.                                            | -                |
| Comment             | Public Note is added to a bonded ticket.                                            | Add a comment to the Incident.                                  | -                |
| Worknote            | Private Note is added to a bonded ticket.                                           | Add a work\_note to the Incident.                               | -                |
| Pending             | State changes to Pending.                                                           | Change state and sync basic ticket fields. Sets On Hold reason. | Awaiting Info    |
| WaitingThirdParty   | State changes to Awaiting Third Party.                                              | Change state and sync basic ticket fields. Sets On Hold reason. | Awaiting Info    |
| Waiting on Customer | State changes to Waiting on Customer.                                               | Change state and sync basic ticket fields. Sets On Hold reason. | Awaiting Info    |
| Resume              | Incident is resumed from an on-hold state. (Awaiting Customer/Third Party/ Pending) | Change state and sync basic ticket fields.                      | In Progress      |
| Resolve             | State is changed to Resolved.                                                       | Change state and sync basic ticket fields.                      | Resolved         |
| ReOpen              | State changes from Resolved to Open.                                                | Change state and sync basic ticket fields.                      | In Progress      |
| Close               | State is changed to Closed.                                                         | Change state, sync basic ticket fields and close bond.          | Closed           |
|                     |                                                                                     |                                                                 |                  |

Transitions between states in Freshservice are shown below:

<figure><img src="https://3662067745-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDk6VgKBXe6rYT8F9wuaY%2Fuploads%2FLqlJJ7XqEifV2mEWu3ED%2FFreshservice-Ticket-Transitions.png?alt=media&amp;token=6ef2ed94-5982-46ba-b09c-83fb81628665" alt=""><figcaption></figcaption></figure>

## Conclusion

With the above guidance, you should be able to configure a Freshservice Webhook 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-07-29 | Initial template |
