fw-attach is a Freshdesk Platform 3.0 sample for a serverless pipeline: ticket attachment → Object Store → Google Drive using a request template (application/octet-stream with "file": { "ref": ... }). It also uploads to Box with multipart/form-data and platform OAuth, includes optional mock templates for octet-stream and multipart, and completes a Slack external file upload using templates for the Web API steps. Together it is a practical reference for automation and request-template setup.
At runtime the app fans out to Google Drive, Box (multipart), and Slack.
- Install –
onAppInstallrequires Freshdesk subdomain and API key; completes withrenderData()or blocks withrenderData({ message })(≤60 characters). - Staging – On
onConversationCreate, download a ticket attachment (Freshdesk attachment URLs are dynamic), upload to Object Store, passfileRefinto templates. - Google Drive –
uploadFileToGoogleDriveuses platform OAuth (config/oauth_config.json, integrationgoogle_drive) and<%= access_token %>— no manual token refresh in code. - Box –
uploadFileToBoxuses platform OAuth (boxinconfig/oauth_config.json),multipart/form-datawithattributes(JSON: name + parent folder) beforefileper Box upload API, and Object StorefileRefonformData.files.file. - Slack –
slackGetUploadURLExternalandslackCompleteUploadExternaluse$request.invokeTemplate; the middle step uploads bytes to the host-specificupload_urlSlack returns fromfiles.getUploadURLExternal.
Serverless logic: server/server.js.
Turn on enable_octet_mock or enable_multipart_mock in install parameters to hit mock hosts defined in config/requests.json and exercise the octet-stream and multipart template shapes without real third-party calls.
- Google Cloud Console → enable Google Drive API.
- Credentials → OAuth client ID (Web application). Add authorized redirect URI:
https://oauth.freshdev.io/auth/callback(andhttp://localhost:10001/auth/callbackfor local FDK). - OAuth consent screen – scope
https://www.googleapis.com/auth/drive.file. - At install, complete Connect for Google Drive in the app settings UI (uses
oauth_config.json). Client ID and secret are collected viaoauth_iparams— not plainiparams.json.
Yes — you need a Box custom OAuth app in the Box Developer Console (Developer → My Apps → Create new app → User Authentication (OAuth 2.0) or equivalent).
- Redirect URIs – add
https://oauth.freshdev.io/auth/callbackandhttp://localhost:10001/auth/callback(local FDK), same pattern as Google. - Application scopes – under Configuration → Application scopes, enable Read all files and folders and Write all files and folders (OAuth equivalents:
root_readonly+root_readwrite).config/oauth_config.jsonsetsoptions.scopetoroot_readonly root_readwriteso the authorize URL explicitly requests both (matches the two checkboxes; reconnect after changing scopes — see Box scopes). - Copy Client ID and Client Secret into install-time Box OAuth fields.
- Set
box_parent_folder_idin iparams to a numeric folder ID (0= user’s “All Files” root). Prefer a dedicated folder ID if root uploads are restricted for your account. Leave empty to skip Box uploads.
Box checks both the app’s scopes and the Box user’s ability to do the same action in the web UI (Box support).
- Re-authorize after scope or
options.scopechanges – Disconnect Box in the app settings and Connect again so Box issues a new token that includesroot_readonlyandroot_readwrite(old tokens stay limited until re-consent). - Folder role (very common) – Box evaluates the user’s permission on the parent folder, not only app scopes. If
box_parent_folder_idpoints at a shared folder where that user is Viewer / preview-only, uploads returnaccess_denied_insufficient_permissionseven when the app has Write all files. Use a folder where the authorizing user is Editor or Uploader (or Co-owner), or a folder they own. Confirm by uploading the same file into that folder in the Box web UI as that user. - Avoid root (
0) when testing enterprise accounts – Some org policies restrict root uploads; create Freshdesk uploads (or similar) in Box, note the folder ID from the URL, setbox_parent_folder_idto that ID. - Enterprise allowlisting – Org admins may need to allow the custom app (third-party / Platform apps settings) before OAuth tokens can access content.
- Server/JWT apps – If you ever switch app type, admins must re-approve scopes under Admin Console → Integrations → Platform Apps Manager.
| Topic | Notes |
|---|---|
| Freshdesk | Serverless onConversationCreate; Object Store + templates for Drive / Box / Slack. |
| Object Store allowlist | PNG, JPEG, CSV, JSON, XLS(X) in this sample. |
| Drive upload | Simple media upload (uploadType=media) via template. |
| Box upload | Multipart attributes + file to upload.box.com (≤50 MB per Box; larger files need chunk upload APIs). |
- Freshdesk subdomain + API key.
- Google – OAuth app + install-time authorization for Drive.
- Box (optional) – OAuth app + folder ID; connect Box at install.
- Slack – Bot token (
files:write), channel ID. See Uploading files.
cd fw-attach
fdk runUse the serverless simulator to exercise onAppInstall and onConversationCreate.
| Path | Purpose |
|---|---|
config/oauth_config.json |
Google Drive (google_drive) + Box (box) OAuth |
config/requests.json |
Drive + Box multipart + Slack Web API + optional mocks |
config/iparams.json |
Freshdesk + Slack + mock toggles |
manifest.json |
onAppInstall, common.requests, support_ticket events |
server/server.js |
Handlers + helpers after exports |
- Do not log API keys, OAuth secrets, or tokens.
- Prefer platform OAuth over pasted access tokens.