> 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-configuring-inbound-attachments.md).

# FreshService: Configuring Inbound Attachments

The following explains how to retrieve attachments from a Freshservice instance, implementation depends on how the integration is built. This guide is based on the attachment object returned by a 'Get Ticket request'. This response looks like the following:

```json
{
    "ticket": {
        "subject": "Ticket with attachments",
        "id": 123,
        ... more details ...
        "attachments": [
            {
                "attachment_url": "https://instance-name.attachments.freshservice.com/data/helpdesk/attachments/production/34000000001/original/example.png?response-content-type=image/png&Expires=1780154239&Signature=344char-uniquestring1__&Key-Pair-Id=SAME4allATTACHMonTKT",
                "content_type": "image/png",
                "created_at": "2026-05-07T16:32:28Z",
                "id": 34000000001,
                "name": "example.png",
                "size": 90001,
                "updated_at": "2026-05-07T16:32:31Z"
            },
            {
                "attachment_url": "https://instance-name.attachments.freshservice.com/data/helpdesk/attachments/production/34000000002/original/Foo.txt?response-content-type=text/plain;charset=utf-8&Expires=1780154239&Signature=344char-uniquestring2__&Key-Pair-Id=SAME4allATTACHMonTKT",
                "content_type": "text/plain;charset=utf-8",
                "created_at": "2026-05-08T08:07:55Z",
                "id": 34000000002,
                "name": "Foo.txt",
                "size": 123456,
                "updated_at": "2026-05-08T08:07:58Z"
            }
        ]
    }
}
```

To Process the attachment inbound we pass the loop through the attachments array and send new attachments to a poller with the following code:

```javascript
// Fetch attachment with a poller
x_snd_eb.Poller.execute(variables.attachment_poller, {
  attachment: attachment, //attachment object
  int_ref: task_number, // Number of the ServiceNow record
  ext_ref: ticket_id + "", // id of the ticket
});
```

Where `variables.attachment_poller` is the sys\_id of a poller we will create in this tutorial.

To retrieve the ticket we make a GET request to Freshservice, this is made by a Poll Processor.

## Attachment Poll Processor

The Attachment Poll Processor requests the attachment from Freshservice and creates an Inbound request to Unifi to log when an attachment has been created.

### Setup Script

Setup script sets the endpoint we will call to retrieve the attachment:

```javascript
// Configure the new Poll Request record
(function (poll_request, poller, params) {
    // Params object includes:
    // params.attachment.id 			eg 40001234567
    // params.attachment.name 			eg example.txt
    // params.attachment.content_type 	eg text/plain;charset=utf-8
    // params.ext_ref : The sys_id of the attachment in the remote system
    // params.int_ref : internal document reference

    var attach_id = params.attachment.id;

		// https://api.freshservice.com/#download_attachment
    poll_request.endpoint_url += '/api/v2/attachments/' + attach_id;

})(poll_request, poller, params);
```

### Request Script

Creates the REST message and makes the request, it also contains code to save the response as an attachment naming it based on the 'name' parameter.

```javascript
// Process the request e.g. by executing a web service and returning the response
(function (poll_request, poller, connection, params) {

  var request, response;
  
  request = new sn_ws.RESTMessageV2();
  request.setHttpMethod('GET');
  request.setEndpoint(poll_request.endpoint_url);
  request.setRequestHeader('Content-Type','application/json');
  request.setBasicAuth(connection.getBasicAuthUser(), connection.getBasicAuthPassword());
  
  // Save the response as a new attachment (on the poll request)
  request.saveResponseBodyAsAttachment(
    poll_request.getTableName(), poll_request.sys_id, params.attachment.name
  );
  
  response = request.execute();
  
  poll_request.response_code   = response.getStatusCode();
  poll_request.response_status = response.getErrorMessage();
  if (response.haveError()) {
    throw '\nResponse Code: ' + response.getErrorCode() + '\nResponse error: ' + response.getErrorMessage();
  }
  
  // Return the sys_id of the saved attachment
  answer = response.getResponseAttachmentSysid() + '';

})(poll_request, poller, connection, params);
```

### Response Script

Response script sends an inbound message to Unifi named 'AddAttachment' with the attachment object and its internal and external references.

```javascript
// Process the response returned by the request script
// The 'answer' variable from the request script is passed in here as the 'response' parameter 
(function (poll_request, poller, response, params) {

  // Establish the environment
  var poll_helper = new x_snd_eb.PollHelper(poll_request);
  var info = [
    'Document: ' + params.internal_ref,
    '- Attachment file name: ' + params.attachment.name,
    '- Attachment id: ' + response
  ];

  // The response should be the sys_id of the created attachment
  params.attachment.data = '<x-attachment-data sys_id="' + response + '" />';
  
  // Build the payload for Unifi
  var payload = {
    external_ref : params.external_ref,
    internal_ref : params.internal_ref,
    attachment   : params.attachment
  };
  
  // Submit the message into Unifi
  poll_helper.processInbound({
    message_name : 'AddAttachment',
    payload : JSON.stringify(payload)
  });

  poll_request.response_status = info.join('\n');

})(poll_request, poller, response, params);
```

## AddAttachment Messaage

The 'AddAttachment' message creates an inbound message to track attachment creation and link it to it's bonded record.

Create a new message 'AddAttachment' on the integration. The fields to be configured are as follows:

| Field        | Description                                                                                           | Value             |
| ------------ | ----------------------------------------------------------------------------------------------------- | ----------------- |
| Message name | The message name that is unique for this integration.                                                 | 'AddAttachment'   |
| Type         | The primary purpose of the message.                                                                   | 'Update'          |
| Direction    | The direction(s) this message is configured to support. *(Choices: Inbound, Outbound, Bidirectional)* | 'Bidirectional'\* |

*Your AddAttachment New Message modal should look like this:*

![](https://docs.sharelogic.com/unifi/~gitbook/image?url=https%3A%2F%2F3662067745-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FDk6VgKBXe6rYT8F9wuaY%252Fuploads%252Fqkdda1LSnwFScUlID54T%252FFT26-AddAttachment-.png%3Falt%3Dmedia%26token%3Dfc0bd40c-a7cf-4c76-a849-9dc4af5ec256\&width=768\&dpr=3\&quality=100\&sign=2e851d8b\&sv=2)

**Submit and view** to further configure the message.

### Message settings <a href="#message-settings" id="message-settings"></a>

The following settings should be configured on the message.

#### Message Bond <a href="#message-bond" id="message-bond"></a>

Navigate to **Message > Bond**

Set the message to be processed in the **Bond pending** & **Bond open** states:

### Inbound Settings <a href="#outbound-trigger" id="outbound-trigger"></a>

Navigate to **Inbound  > Settings**

For **Bond Reference method** set 'External'.

### Inbound Scripts <a href="#outbound-attachments" id="outbound-attachments"></a>

For inbound scripts we simply map the external reference from the external reference sent by our poller. This links the message to our bonded record.

#### Payload to Stage (Inbound)

{% code lineNumbers="true" %}

```javascript
(function processPayloadToStage(payload, stage, transaction, message) {

  // set either internal/external reference on stage depending on what is needed.
  // make sure to configure the Bond reference lookup on the Message to be Internal/External
		stage.external_reference = payload.external_reference;
    //stage.internal_reference = payload.internal_reference;

})(payload, stage, transaction, message);
```

{% endcode %}

#### Stage to Target (Inbound)

Stage to Target is empty as we already added the attachment to our record in the Poll processer.

{% code lineNumbers="true" %}

```javascript
// Empty
```

{% endcode %}

## Next Steps...

With this in place, you should be able to retrieve attachments from Freshservice.

Depending on the attachment setup you may wish to add [Data Stores](/unifi/configure/administration/data-stores.md) to the bond to store attachment id's retrieved so they may be filtered out of future retrievals. An example of this can be found on the Freshservice Polling template.&#x20;

### Embedded attachments

Attachments added to Notes can be retrieved with the method above by passing them into the attachment poller.

Images embedded in Notes can be retrieved with the same method with some minor modifications. These appear in the note payload as `<img src="https://attachment.freshservice.com/inline/attachment?token=eyJ.longtoken" ... >`. Of this the url can be extracted validated and called using a separate Poll processor. As we don't have the name or filetype of this image, we pass a generic filename and the content-type: `image/*` . The attachment can then be sent into the same 'AddAttachment message. The image should be added to work\_notes though the version attached to the integrated record will error as filetype is unknown.&#x20;
