> ## Documentation Index
> Fetch the complete documentation index at: https://docs.serval.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Freshservice

> Freshservice is an IT service management (ITSM) platform - Serval connects to your instance to sync tickets and knowledge articles, ingest service catalog items as runnable workflows, and take actions through the Freshservice API.

## About Freshservice

Freshservice is an IT service management (ITSM) platform from Freshworks. The Serval Freshservice integration connects to your Freshservice instance using your instance domain and an agent API key. A single connection powers ticket sync, optional real-time ticket webhooks, knowledge base sync, and service catalog ingestion - plus workflow actions for placing catalog requests, uploading attachments, and calling any part of the Freshservice API.

**Authentication:** API key (HTTP Basic auth). You provide your Freshservice domain and an agent API key; the key is a long-lived credential that inherits the permissions of the Freshservice agent who generated it. There is no OAuth flow and no token refresh.

**Data sync:** Tickets sync via background polling every 30 seconds by default, or in real time via webhooks (enabling webhook sync turns polling off). Knowledge base content syncs on a recurring schedule. Service catalog syncs are triggered manually from the UI. Workflow actions call Freshservice on demand.

## What the Freshservice integration enables

| Capability                | Description                                                                                                                                                                                                                 |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ticket sync               | Background polling every 30 seconds. Covers tickets, ticket conversations (comments and replies), requesters (including lookup by email), groups, locations, workspaces, status options, and ticket form fields.            |
| Real-time ticket webhooks | Two inbound webhooks - one for ticket field changes, one for new replies and forwards - authenticated with a secret token header. Enabling webhook sync replaces polling.                                                   |
| Knowledge base sync       | Syncs solution categories, folders, subfolders, and articles on a schedule. Serval can also create and update articles.                                                                                                     |
| Service catalog ingestion | Imports your service catalog items as runnable external workflows, including their request form fields and dropdown choices. Deleted and draft items are skipped. Syncs are triggered manually from the UI.                 |
| Catalog item requests     | Places a service catalog request on a requester's behalf, with quantity, optional subject, custom form fields, and optional attachments (attached afterward as private, agent-only notes on the resulting service request). |
| Attachment upload         | Adds a file attachment to a service request. Because the Freshservice API has no direct attachment upload, the file is posted as a note on the ticket (public by default).                                                  |
| Generic API access        | Any Freshservice REST API call, proxied to your instance with authentication injected automatically.                                                                                                                        |

Anything defined in the [Freshservice API](https://api.freshservice.com/) can be accessed through Serval.

## Get your credentials

Serval authenticates with an API key that belongs to a Freshservice **agent**. We recommend a dedicated **full-time agent service account** with the **Account Administrator** account-wide role (or a custom role with workspace management permissions - the connection health checks require one of the two) plus a custom workspace role granting ticket view/reply/edit/create permissions in every workspace Serval should sync. See Freshservice's official guide to [finding your API key](https://api.freshservice.com/#authentication).

<Warning>
  The account must be an **Agent** (not a Requester) and a **Full-time Agent** (not Occasional). The agent must also complete activation - accept the invitation email and set a password - or its API key will not work.
</Warning>

<Steps>
  <Step title="Create the service-account agent">
    In Freshservice, go to **Admin** → hamburger menu (top left) → **Global Settings** → **Agents** (User Management section) → **New Agent**. Set a descriptive name and email, and set **Agent Type = Full-time Agent**.
  </Step>

  <Step title="Grant the account-wide admin role">
    On the agent's profile → **Permissions** → **Add admin role** (account-wide), select **Account Administrator** → **Save**. The connection health checks expect the key's user to have this role (or a custom role with workspace management permissions) to list your workspaces.
  </Step>

  <Step title="Create a custom ticket role">
    Go to **Admin** → **Global Settings** → **Roles** → **New role** (e.g. "Serval Supervisor") with at minimum: View tickets; Send reply to a ticket; Forward a conversation; Edit everyone's notes; Delete a conversation; Merge / split a ticket; Edit ticket properties; Move tickets; Create and Edit Tasks in Tickets (allow reordering); Delete a ticket; Export Tickets.
  </Step>

  <Step title="Add the agent to every workspace Serval should sync">
    On the agent's **Workspace permissions** → **Add to workspace** → **Add role** → select the custom role "across the workspace". Repeat for every workspace Serval should sync; for restricted groups, also add the agent to the group itself.
  </Step>

  <Step title="Activate the agent and copy the API key">
    Accept the invitation email and set a password, then sign in as the agent → **Profile Settings** (top-right avatar) → **API Settings** → ensure the API key is enabled and copy it.
  </Step>
</Steps>

<Note>
  Serval's connection health checks expect the key's user to have the **Account Administrator** role (or a custom role with workspace management permissions) and membership in **at least one workspace**. The API key inherits exactly the permissions of the agent it belongs to - nothing more.
</Note>

## Connect in Serval

The connect form has exactly two fields: **Domain** and **API Key**.

<Steps>
  <Step title="Enter your Domain (required)">
    The field asks for "Your Freshservice domain (without https\://, e.g., company.freshservice.com)". Enter the bare domain - Serval normalizes the value by trimming whitespace and stripping any leading "http\://" or "https\://" and trailing slashes. Leaving it empty fails with: "API domain is required".
  </Step>

  <Step title="Enter your API Key (required)">
    A password-type field described as "API key generated in Freshservice Admin settings". Paste the agent API key you copied above. Leaving it empty on first connect fails with: "API key is required".
  </Step>

  <Step title="Save the connection">
    Submit the form. Serval stores the API key encrypted and uses your domain as the base for every request to Freshservice.
  </Step>
</Steps>

<Note>
  The webhook token is **not** on the connect form. Serval generates it automatically and displays it as the read-only **"Authentication Token"** on the integration's ticket sync settings page, alongside the **"Ticket Update Webhook URL"** and **"New Reply Webhook URL"** copy fields and the name of the header to send it in. You only need it if you set up real-time ticket webhooks.
</Note>

<Tip>
  When **updating** an existing connection, blank fields keep their previously stored values. You can rotate just the API key without re-entering the domain - and vice versa. The stored webhook token is preserved too.
</Tip>

## Verifying the connection

Serval runs three health checks after you connect:

**Validate Freshservice Workspace Access** - confirms your API key can list the workspaces in your instance (requires the Account Administrator role or a custom role with workspace management permissions).

* Success: "Successfully accessed Freshservice workspaces. Found \[number] workspace(s)."
* Permissions failure: "Unable to access Freshservice workspaces. Your API token lacks the required permissions. Please reconnect using an API token from a user with the 'Account Administrator' role or a custom role with workspace management permissions."
* Other errors: "Unable to connect to Freshservice API. Please verify your API token is valid and your Freshservice domain is correct."

**Validate Ticket Form Fields Access** - confirms the key's user is a member of at least one workspace by reading ticket form fields for your first workspace.

* Success: "Successfully validated access to Freshservice ticket form fields. During ticket sync configuration, you'll see workspaces you have access to."
* Not a workspace member (403): "Unable to access Freshservice workspace form fields (403 Forbidden). This indicates the API token user is not a member of any workspaces. Please either:
  • Add this user to one or more workspaces in Freshservice (Admin → Workspaces), OR
  • Use an API token from a user with 'Account Administrator' role
  Note: During ticket sync configuration, the workspace dropdown will automatically show only workspaces you have access to."
* No workspaces exist: "No Freshservice workspaces found. Please ensure your Freshservice instance has at least one workspace configured."
* Invalid key (401): "Freshservice API authentication failed (401 Unauthorized). Your API token is invalid or expired. Please reconnect with a valid API token."
* Other errors: "Unable to read ticket form fields from Freshservice. Please verify your API token is valid and has proper permissions."

**List Freshservice Tickets** - confirms the key can read tickets.

* Success: "Successfully retrieved tickets from Freshservice." (or, if your instance has no tickets yet: "Successfully connected to Freshservice tickets API (no tickets found).")
* Failure: "Unable to read tickets from Freshservice. Please verify your API token has permissions to access tickets."

<Tip>
  All three checks can pass and ticket updates can still stop flowing - the most common cause is flipping "Enable webhook sync" before both Freshservice Workflow Automators are configured and active. The toggle disables polling, so until your webhooks deliver, no updates arrive at all.
</Tip>

## Gotchas and troubleshooting

<AccordionGroup>
  <Accordion title="API key permissions are the #1 failure mode">
    The key inherits the agent's permissions. The health checks specifically require the Account Administrator role (or a custom role with workspace management permissions) to list workspaces, and membership in at least one workspace to read ticket form fields. A Requester account, an Occasional Agent, or a never-activated agent produces 401/403 errors.
  </Accordion>

  <Accordion title="Enabling webhook sync turns polling OFF">
    The UI toggle "Enable webhook sync" states: "Enable after configuring webhooks. Polling will be disabled and ticket updates will come through webhooks only." Configure and activate both Freshservice Workflow Automators before flipping it, or ticket updates stop flowing.
  </Accordion>

  <Accordion title="Two separate webhooks, strict paths, and a token header">
    Ticket field changes and new replies use two different webhook URLs - copy the "Ticket Update Webhook URL" and "New Reply Webhook URL" exactly from the ticket sync settings page. An unknown path is rejected with "Unknown webhook path; use /freshservice/ticket-update or /freshservice/reply". Every request must carry the X-Serval-Webhook-Token header matching the stored webhook token (an empty stored token or missing header fails validation), the ticket source must have webhooks enabled, and the payload must include a ticket ID. Don't include "Latest Public Comment" in the ticket-update automator - comment data belongs only on the reply webhook.
  </Accordion>

  <Accordion title="Webhook routing depends on the Helpdesk URL in the payload">
    Serval resolves which connection a webhook belongs to from the payload's Helpdesk URL field (falling back to a domain segment embedded in the URL path). Include Helpdesk URL in the automator's Content selection. Display ticket IDs like INC-3982 are normalized to the numeric 3982 automatically.
  </Accordion>

  <Accordion title="The connect form has only two fields; the webhook token lives elsewhere">
    The form asks for Domain and API Key only. The webhook token is the read-only "Authentication Token" on the integration's ticket sync settings page - Serval generates and stores it automatically the first time that page loads - and it is only used to authenticate inbound webhooks.
  </Accordion>

  <Accordion title="Enter the domain bare - it gets normalized anyway">
    The field description explicitly asks for the domain without https\://. The form strips leading "http\://" or "https\://" and trailing slashes before submitting, so "[https://company.freshservice.com/](https://company.freshservice.com/)" becomes "company.freshservice.com".
  </Accordion>

  <Accordion title="Blank fields on update keep existing values">
    The update path only overwrites the API key or domain when a non-empty value is submitted. Leaving a field blank preserves what's stored - safe for rotating a single credential. The Serval-generated webhook token is never collected by the form and is always preserved.
  </Accordion>

  <Accordion title="Catalog sync is manual and filters items">
    Scheduled catalog sync is intentionally paused - trigger syncs from the UI. The sync skips deleted and draft (unpublished) items, caps lookup-field dropdowns at 12 choices, retries transient gateway errors up to 2 times, and marks items with required unsupported fields (attachments, nested/dependent dropdowns, lookups whose choices couldn't be fetched) as unfillable, falling back to a link to the item's form in your Freshservice Service Portal.
  </Accordion>

  <Accordion title="Attachments go through ticket notes">
    The Freshservice API v2 has no direct attachment upload, so Serval posts files as notes on the ticket. Attachments on catalog requests are uploaded as private, agent-only notes; the standalone attachment-upload action defaults to a public note.
  </Accordion>

  <Accordion title="Connections created before webhook support lack a webhook token">
    Older connections created under the original API-key-only storage format cannot hold a webhook token - the ticket sync settings page shows "Not configured" as the Authentication Token and webhook validation fails. Saving any update to the connection automatically migrates it to the new storage format; after that, Serval generates the token the next time the ticket sync settings page loads.
  </Accordion>

  <Accordion title="Generic API responses are wrapped and paginated">
    Freshservice wraps responses by resource type (for example, a list of tickets arrives under a "tickets" key) and uses page-based pagination - a page number plus a per-page size of up to 100 records - so loop until an empty page. Rate limits are strict; add delays between paginated requests on large datasets.
  </Accordion>
</AccordionGroup>

***

Need help? Contact **[support@serval.com](mailto:support@serval.com)** for assistance with your Freshservice integration.
