Ticket integrations
Connect Momentum to your ticket system for bi-directional sync. Currently shipping: Freshdesk. Zendesk is next on the roadmap (Phase 34).
Connecting Freshdesk
- In Freshdesk, go to Profile → API Key. Copy the key.
- In Momentum, go to Settings → Integrations → Add integration. Pick Freshdesk.
- Enter your subdomain (
yourcompany.freshdesk.com) and the API key. Momentum runs a test call before saving. - On save, you'll see a one-time modal with the webhook URL + secret to paste into Freshdesk. This is your only chance to see the secret — copy it now.
- In Freshdesk, go to Admin → Automations → Webhooks and configure:
- URL: the Momentum webhook URL (
/api/webhooks/freshdesk/{integrationId}) - Custom header:
X-Momentum-Webhook-Secret: {your secret} - Triggers: ticket created, updated, status changed
- URL: the Momentum webhook URL (
Importing tickets
From the Cases page, the "Import from Freshdesk" button opens a two-tab modal:
- By ticket IDs — paste a list of Freshdesk ticket IDs to import specific tickets.
- By filter — pick a status, updatedSince, and limit. Momentum pages through matching tickets and imports them.
Imports are idempotent. The composite unique index cases_external_link_uq (workspace_id, external_provider, external_ticket_id) prevents duplicate cases even if you re-run the same import.
Customers are auto-linked by email or domain; new customer rows are created with externalId = "freshdesk:{email}" when no match exists.
Bi-directional sync
After a case is linked to a Freshdesk ticket, changes flow both ways:
- Inbound — webhook events from Freshdesk update the Momentum case (status, priority, assignee, comments).
- Outbound — edits in Momentum push back to Freshdesk. Comments can optionally push as private notes (off by default).
Loop prevention
Two layers of loop prevention keep bi-directional sync from echoing itself:
- Source tagging. The shared
updateCase()helper takes an explicitsourceargument ("user" | "import" | "webhook" | "reconciler"). Only user-initiated changes trigger outbound push. - 10-second dedup. Before any outbound push, Momentum checks
ticket_sync_logfor a matching inbound event within the last 10 seconds. Matches are dropped.
The reconciler
A reconciler runs every 10 minutes inside Hocuspocus. For each linked case, it fetches the Freshdesk ticket and reconciles state divergences. It is a safety net for dropped webhooks — not a primary sync path.
The reconciler only reconciles; it never creates new cases. Imports are always explicit.
Security
- Credentials — stored AES-256-GCM encrypted at rest using the
ENCRYPTION_KEYenv var (64-char hex). - Webhook verification — incoming webhooks are verified with
crypto.timingSafeEqualagainst the per-integration secret. - Dedup by event ID — Freshdesk webhooks are deduped by their event ID; replays are no-ops.
Coming soon
- Zendesk (Phase 34) — OAuth, bi-directional sync, feature parity with Freshdesk.
- Cross-integration unified inbox — tickets from multiple systems in one Momentum view.