Freshdesk CTI global sidebar sample based on the Freshdesk CTI tutorial. It loads your Zoom agent profile in the CTI pane and includes a demo dial pad built with Crayons React (FwSpinner, circular keys, layout).
Built on Freshworks Platform 3.0 (React Meta, Node 24.11.1, FDK 10.1.2).
Nimbus Contact Center agents work Freshdesk tickets while voice runs on Zoom. zoomdesk confirms the linked Zoom agent in the CTI strip and prototypes a Crayons dial pad before production telephony. See usecase.md for the full Nimbus operational scenarios.
- Agent card — real integration showing name, email, and Zoom user ID from
/users/mevia server-side OAuth - Dial pad + Call — UI demo only; illustrates Crayons styling and CTI layout (does not place production calls)
- SMI
getAgent— exchanges S2S credentials and fetches Zoom profile server-side - CTI resize — sidebar tuned for the Freshdesk headset strip on activate
| Part | Purpose |
|---|---|
| Agent card | Real integration — shows name, email, and Zoom user ID from Zoom (/users/me) via server-side OAuth |
| Dial pad + Call | UI demo only — illustrates Crayons styling and CTI layout; does not place production calls |
| Surface | Placement | Behavior |
|---|---|---|
app/index.html |
common.cti_global_sidebar |
Zoom agent card, demo dial pad, Refresh |
The app loads in cti_global_sidebar with a blue Z icon. Agents open the CTI panel from the Freshdesk headset strip.
client.request.invoke('getAgent') triggers serverless OAuth token exchange and Zoom GET /users/me.
| Template | Purpose |
|---|---|
zoomAccessToken |
POST token with S2S credentials |
zoomUserMe |
GET agent profile |
Account ID, Client ID, and secure Client Secret from the Zoom Server-to-Server OAuth app.
The app uses Freshworks Crayons v4 design system:
| Component | Usage |
|---|---|
FwSpinner |
Loading state while fetching agent profile |
| Circular keypad | Demo dial pad layout |
| Custom CSS | Zoom-blue branding and CTI sizing |
- Node 24.11.1 and FDK 10.1.2
- A Freshdesk account (for local testing with
?dev=true) - A Zoom account where you can create a Server-to-Server OAuth app
- Open Zoom Marketplace and sign in.
- Go to Develop → Build App.
- Choose Server-to-Server OAuth → Create.
- Enter an app name (e.g.
zoomdesk-dev) and complete the basic info.
- In the app, open Scopes.
- Click Add Scopes.
- Add
user:read:admin(under Users). - Save.
- Open Activation.
- Click Activate for your Zoom account (account admin may be required).
- Open App Credentials (or Basic Information → credentials section).
- Copy and store these three values — you will paste them into Freshdesk developer settings:
| Credential | Where it appears |
|---|---|
| Account ID | App Credentials page |
| Client ID | App Credentials page |
| Client Secret | App Credentials page (shown once; regenerate if lost) |
Keep the Client Secret private. Do not commit it to git.
From the app folder:
cd only-migration/cti-tutorial-freshdesk
npm install
fdk validate
fdk runLeave fdk run running. Note the local URLs printed in the terminal (typically http://localhost:10001).
While fdk run is active, configure installation parameters for your dev account.
-
Open http://localhost:10001/custom_configs in your browser.
-
Enter:
Field Value Zoom Account ID From Step 1.4 Zoom Client ID From Step 1.4 Zoom Client Secret From Step 1.4 -
Save.
- Open http://localhost:10001/system_settings.
- Set the same three Zoom fields if shown for your product.
- Save.
- Open your Freshdesk site with the dev flag, for example:
https://yourdomain.freshdesk.com/a/→ add?dev=true
(use&dev=trueif the URL already has query parameters). - When the browser asks to allow local network access, allow it (required for
fdk run). - Click the CTI headset strip and select the blue Z (zoomdesk) icon.
- Confirm the Agent card shows your Zoom name and email after a few seconds.
- Use Refresh if you changed credentials.
The dial pad and Call button are for trying the UI only. They are not documented as a supported calling integration.
| Symptom | What to check |
|---|---|
| Agent card empty or error | All three fields saved in custom configs; S2S app activated; scope user:read:admin added |
| App does not load in Freshdesk | fdk run still running; ?dev=true on URL; local network allowed |
| Invalid Client Secret | Regenerate secret in Zoom App Credentials and update custom configs |
cti-tutorial-freshdesk/
├── app/
│ ├── components/ CtiMain.jsx, ZoomdeskApp.jsx
│ ├── utils/ phone.js (demo dial helper)
│ ├── icon.svg
│ └── styles/ style.css, zoom-banner.png
├── config/ iparams.json, requests.json
├── server/ server.js (getAgent)
├── manifest.json
├── README.md
└── usecase.md
fdk validate
npm run fdk-unit-testTarget: 0 platform errors, 0 lint errors.
npm run fdk-unit-testReset local installation parameters when re-testing Zoom credentials:
rm .fdk/store.sqlite
fdk run- Secrets stay server-side — Zoom Client Secret is a secure iparam; only
getAgentinvokes OAuth templates. - CTI vs ticket sidebar —
cti_global_sidebaruses different resize and event patterns (cti.triggerDialer) than ticket sidebars. - Demo vs production calling — document dial pad scope clearly; use Zoom's official integration for live telephony.
- Minimal S2S scope —
user:read:adminis enough for agent identity without Contact Center API complexity.
