CortexDB Docs
Connectors

Freshdesk Connector

Ingest Freshdesk tickets, replies, private notes, and attachments into CortexDB.

Captures Freshdesk tickets, their full conversation thread (public replies + private notes), and their attachments as CortexDB experiences. Each item keeps its real source timestamp.

Two ways to run this connector

Self-hostedpip install cortexdb-connectors then cortexdb-sync sync freshdesk. Managed — CortexDB runs the connector as a worker. See the Connectors overview.

Upgrade to 0.2.20

Earlier versions silently lost data: a ticket that reached 10 conversations stopped ingesting new replies forever, a rate-limited detail fetch stored the ticket with no body, and attachments were dropped entirely. See Upgrading.

1. Prepare credentials in Freshdesk

Freshdesk → Profile settings → Your API Key. The connector authenticates as HTTP Basic with the API key as the username and X as the password. You also need your Freshdesk domain, e.g. acme.freshdesk.com.

2. Configure (managed dashboard)

Settings → Connectors → Add Connector → Freshdesk. Paste the domain and API key, set the scope template (default org:<org>/source:freshdesk), and Start sync.

What gets written

EventEpisode typeNotes
TicketissueSubject + description; content prefixed [FreshDesk ticket #N]
Public replycommentPrefixed [FreshDesk reply on ticket #N]; tagged reply
Private notecommentPrefixed [FreshDesk note on ticket #N]; tagged note
Ticket/reply attachmentdocumentUploaded to /v1/blobs and ingested as content.kind="blob_ref" so the content processors extract and index the file

Every episode carries thread_id = "freshdesk:ticket:<id>", an entity reference of type ticket, and metadata with ticket_id, status, priority, and a source_url back to the agent view.

Visibility

All Freshdesk episodes are stored restricted — support data is customer-facing and sensitive. Public replies and private notes land at the same visibility; the distinction is carried by the reply / note tag and the content prefix.

Idempotency and history

Tickets and conversations use a content-versioned key:

ticket:<id>:<updated_at>:<content-digest>
conv:<id>:<created_at>:<content-digest>
freshdesk:att:<attachment_id>

Each edited state is retained as a new version. The content digest is what makes edited replies and merged tickets work: a Freshdesk merge moves conversations to the primary ticket without changing their id or created_at, so a timestamp-only key would collide and the corrected attribution could never be recorded. Attachments key on the stable attachment id, so a re-synced ticket replays instead of re-uploading the bytes.

Real-time delivery (webhook)

Freshdesk automations don't sign their payloads, so the receiver authenticates on a static header:

export FRESHDESK_WEBHOOK_SECRET=<a long random string>
cortexdb-sync serve --port 8081

Then in Freshdesk → Admin → Workflows → Automations, add a Trigger webhook action pointing at POST https://<your-host>/webhooks/freshdesk/events with Authorization: Bearer <the same secret>. The webhook path uses the same normalizer as polling, so running both serve and sync is safe.

Run it yourself

pip install cortexdb-connectors
pip install cortexdb-cli && cortexdb init

export FRESHDESK_DOMAIN=acme.freshdesk.com   # required
export FRESHDESK_API_KEY=...                 # required
export FRESHDESK_INCLUDE_CONVERSATIONS=1     # 0 = tickets only, bodies still ingested
export FRESHDESK_INCLUDE_ATTACHMENTS=1       # 0 = skip attachment blobs

cortexdb-sync --api-url http://localhost:3141 sync freshdesk
cortexdb-sync --api-url http://localhost:3141 watch freshdesk --interval 300

FRESHDESK_INCLUDE_CONVERSATIONS=0 drops only the reply and note episodes — the ticket description is always ingested.

Limits and behaviour worth knowing

  • Attachments over 32 MiB are recorded metadata-only: the filename survives, the bytes are not uploaded.
  • Rate limits are handled: requests retry 429/5xx with Retry-After, up to 5 attempts.
  • A ticket that cannot be fetched holds the cursor and is retried; after 5 consecutive failed cycles it is dead-lettered and cortexdb-sync status reports it.
  • Deletions are not propagated from the poll path — a deleted reply remains as retained history.

Upgrading from 0.2.19 or earlier

0.2.20 fixed several silent data-loss paths. The most impactful: tickets that reached 10 conversations stopped ingesting — the thread was read from a preview array capped at 10 entries, so every later reply, note, and resolution was invisible while the sync reported success. To backfill:

cortexdb-sync status                      # note the current cursor first
cortexdb-sync sync freshdesk --since 2020-01-01T00:00:00Z

Re-ingest is safe — idempotency keys dedupe anything already stored. Because keys now carry a content digest, the first sync after upgrading records one new version per currently-visible ticket state.

See also

On this page