Skip to content

Repository files navigation

Request Methods

Nexus Connect Hub — Request Method Samples

A Freshworks Platform 3.0 sample app that teaches Request Methods through real integration scenarios — partner webhooks, account sync, priority search, health checks, and resilient lookups — the way Nexus API Labs ships client connectors.

The full-page Integration Ops Center maps each client workflow to a requests.json template with Run integration drills. The ticket Quick Connect sidebar builds payloads from client.data.get('ticket') and invokes through SMI. A collapsible Developer playbook holds schema tables and platform limits for engineers. See usecase.md for Nexus operational scenarios.

Description

Nexus API Labs integrates Freshdesk with partner CRMs, billing APIs, and webhooks. Instead of a dry API catalog, this app presents scenario cards — each card tells a client story, shows the template key, and runs a live server-side invoke. New engineers learn why a pattern exists before opening the playbook reference tables.

Scenario metadata lives in request-objects.js; cards and sidebar actions are rendered by render-catalog.js.

Core Functionality

  1. Integration Ops Center (full page) — scenario card grid for five live client workflows plus future-pattern reference cards
  2. Quick Connect (ticket sidebar) — ticket context banner + one-click integration drills with ticket-derived payloads
  3. SMI invoke wrapperinvokeRequestTemplate routes all live drills through serverless $request.invokeTemplate
  4. Developer playbook — collapsed accordion with limits, schema, substitutions, errors, and allow-list IPs
  5. Front-end cache demo — partner status lookup with cache and ttl (teaching panel inside playbook)
  6. Vitest coveragerequest-kit.js, request-objects.js catalog completeness, and server.js SMI handler

Features

  • Five live integration scenarios — each maps a Nexus client workflow to a template key with colored badge, story text, and formatted response panel
  • Ticket-aware sidebar — webhook body includes ticket id, subject, priority; search query uses current ticket priority
  • Run integration + Copy server code — every scenario card invokes via SMI and copies $request.invokeTemplate sample
  • Future client patterns — CRM upload, OAuth, TLS reference cards (not live in Freshdesk)
  • Iparam-driven Freshdesk calls — account sync and search use encode(iparam.api_key) — keys never reach browser code
  • Themed Nexus branding — hero header, scenario accents, and Quick Connect layout (similar spirit to Agent Huddle sticky notes)

User Interfaces

SurfacePlacementBehavior
app/full_page.htmlcommon.full_page_appIntegration Ops Center — scenario card grid + developer playbook
app/sidebar.htmlsupport_ticket.ticket_sidebarQuick Connect — ticket context + integration action buttons

Scenario → template mapping

Scenario (UI)Template keyNexus client workflow
Partner webhook notifypostWithBodyPOST ticket event JSON to partner webhook at invoke time
Priority escalation searchsearchTicketsFreshdesk search API with dynamic context.query
Account ticket synciparamHostGetList tickets via iparam subdomain + secure API key
Partner API health checkpublicGetRuntime host/path substitution for partner endpoint probe
Resilient partner lookupwithRetryOptionsRetry on transient 429/5xx with options.maxAttempts

Full-page sections

SectionContent
Live integration drillsFive scenario cards with Run integration
Future client patternsReference JSON for upload, OAuth, TLS
Developer playbook (collapsed)Platform limits, schema, substitutions, errors, caching demo

Platform 3.0 Features Used

1. Request Methods — Template Configuration

Five templates in config/requests.json demonstrate host/path substitution, iparam auth, Freshdesk search, POST bodies at invoke time, and retry options:

{
"publicGet": {
"schema": {
"protocol": "https",
"method": "GET",
"host": "<%= context.host %>",
"path": "<%= context.path %>"
}
}
}
TemplateDemonstrates
publicGet<%= context.host %> and <%= context.path %> substitution (swapi.dev demo)
iparamHostGetiparam.subdomain, encode(iparam.api_key), context per_page query
searchTicketsFreshdesk /api/v2/search/tickets with <%= context.query %>
postWithBodyPOST to httpbin.org with JSON body at invoke time
withRetryOptionsoptions.maxAttempts and options.retryDelay on transient failures

2. SMI — Serverless Template Invocation

Production UIs should route sensitive API calls server-side. Scenario cards and Quick Connect call client.request.invoke('invokeRequestTemplate', …):

// app/scripts/request-kit.jsawaitclient.request.invoke('invokeRequestTemplate',{templateName: 'publicGet',context: {host: 'swapi.dev',path: '/api/people/1'}});
// server/server.jsconstresult=await$request.invokeTemplate(args.templateName,{context: args.context||{},body: args.body});renderData(null,result);

3. Installation Parameters — Subdomain and API Key

config/iparams.json supplies values for template substitution at runtime:

IparamPurpose
subdomainAccount subdomain for <%= iparam.subdomain %>.freshdesk.com host substitution
api_keySecure key used with encode(iparam.api_key) in Authorization headers
tls_caOptional PEM for options.security.ca TLS troubleshooting
"headers": {
"Authorization": "Basic <%= encode(iparam.api_key) %>"
}

4. Front-End invokeTemplate and Response Caching

The catalog includes a Front-end response caching panel that calls client.request.invokeTemplate directly with cache: true and ttl: 60000. This is valid for teaching front-end caching behavior; production apps with secrets should still prefer SMI.

client.request.invokeTemplate('publicGet',{context: {host: 'swapi.dev',path: '/api/people/1'},cache: true,ttl: 60000});

Note: Request method calls from the front end are not supported in end-user production apps. This showcase uses SMI for live demos and isolates direct invokeTemplate to the caching panel only.

5. Crayons UI Components

The catalog uses Freshworks Crayons v4 (see catalog-helpers.js and render-catalog.js):

ComponentUsage
<fw-accordion>Collapsible reference panels and live template sections
<fw-button>Invoke (SMI), Copy sample, Invoke with cache
<fw-spinner>Loading state while catalog mounts

Project Structure

├── app/
│ ├── full_page.html # Request method reference catalog (primary surface)
│ ├── sidebar.html # Ticket sidebar pointer to full-page catalog
│ ├── scripts/
│ │ ├── request-objects.js # Platform limits, schema, substitutions, templates
│ │ ├── request-kit.js # SMI invoke, direct invoke, cache helpers
│ │ ├── render-catalog.js # Accordion panels + Invoke buttons
│ │ ├── catalog-helpers.js # Shared accordion/button HTML
│ │ ├── page-init.js # app.initialized() → RequestKit.setClient()
│ │ ├── full_page.js # Mount ops center on full-page surface
│ │ └── sidebar.js # Ticket context + Quick Connect actions
│ └── styles/
│ ├── style.css
│ └── images/icon.svg
├── config/
│ ├── requests.json # Five live request templates
│ └── iparams.json
├── server/
│ └── server.js # SMI: invokeRequestTemplate → $request.invokeTemplate
├── tests/
│ ├── app.test.js # request-kit + request-objects coverage
│ └── server.test.js # SMI handler (VM-loaded exports pattern)
├── manifest.json
├── package.json
├── usecase.md
└── readme.md

Prerequisites

  • Freshworks CLI (FDK) v10.1.2 or later
  • Node.js v24.x
  • A Freshdesk trial account with an API key for searchTickets / iparamHostGet demos

Enable global apps before local development:

fdk config set global_apps.enabled true

Local Development

  1. Install dependencies and validate:

    npm install
    fdk validate
  2. Run locally:

    fdk run
  3. Install the app on a Freshdesk account and configure iparams (subdomain, api_key).

  4. Open surfaces with ?dev=true:

    TestWhere
    Integration Ops CenterLeft navigation → Nexus Connect Hub
    Quick ConnectOpen any ticket → app in right sidebar
  5. Optional — extend request timeout for slow third-party APIs:

    fdk config set request.timeout 20000

    Valid values: 15000, 20000, 25000, 30000 (default 15000).

Where to test integration drills

  1. Partner webhook notify — Full page or sidebar; sidebar POSTs ticket id/subject/priority to httpbin.
  2. Priority escalation search — Sidebar builds query from ticket priority; full page uses "priority:3".
  3. Account ticket sync — Requires iparams; lists one ticket from your Freshdesk account.
  4. Partner API health check — No iparams; probes swapi.dev via context substitution.
  5. Resilient partner lookup — GET with retry options from requests.json.
  6. Developer playbook — Expand collapsed section for schema tables and cached lookup demo.

Implementation Steps

  1. Define templates — add HTTP schema (and optional options) to config/requests.json.
  2. Declare in manifest — list template names under modules.common.requests and register SMI function invokeRequestTemplate.
  3. Configure iparamssubdomain, secure api_key, optional tls_ca for substitution and TLS.
  4. Bootstrap clientpage-init.js calls app.initialized(), sets RequestKit.setClient(), dispatches request-kit:ready.
  5. Mount ops centerfull_page.js listens for request-kit:ready and calls CatalogUI.mount('catalog').
  6. Sidebar contextsidebar.js loads client.data.get('ticket'), mounts Quick Connect with buildSidebarInvokeArgs.
  7. Live invoke pathCatalogUI.invokeSmi / invokeSidebarRequestKit.invokeViaSmi → SMI → $request.invokeTemplate.
  8. Display resultsRequestKit.formatResponse pretty-prints the response string from the invoke result.

How request method works

  1. Configure templates in config/requests.json (HTTP schema + optional options).
  2. Declare template names under modules.common.requests in manifest.json.
  3. Invoke from serverless ($request.invokeTemplate) or front-end (client.request.invokeTemplate).

Platform limits

ConstraintValue
Request timeout15s default; 20–30s extends app execution to 40s
Rate limit50 requests/min per app per account
Request body max100 KB to serverless
Response max6 MB
Max templates100 in requests.json

config/requests.json

Each template is a JSON object keyed by <requestTemplateName>.

Schema attributes

AttributeRequiredDescription
methodYesGET, POST, PUT, DELETE, PATCH
protocolNoHTTPS in production; HTTP for local testing only
hostYesFQDN only — no protocol, trailing slash, or IP
pathNoResource path starting with / (default /)
queryNoQuery parameters as key-value pairs
headersNoHTTP headers (Authorization, Content-Type, etc.)
formDataNomultipart/form-data fields and file refs (object store)
fileNoapplication/octet-stream upload via object store ref

Note: The HTTP request body is not part of the template schema; pass it at invoke time.

Options attributes

OptionDescription
maxAttemptsRetry count on network or 429/5xx errors (1–5, default 1)
retryDelayMilliseconds before retry (1–1500, default 1000)
oauthOAuth config name from config/oauth_config.json
security.caPEM CA certificate for TLS chain issues
security.certPEM client certificate
security.keyPEM private key
security.pfxBase64 cert+key bundle
security.passphrasePassword for key or PFX

Template substitutions

Variables are resolved at runtime in schema attributes:

SyntaxUsed inPopulated by
<%= iparam.name %>host, path, query, headersInstallation parameters
<%= encode(iparam.name) %>headersSecure iparams (e.g. API keys)
<%= context.name %>host, path, query, headersInvoke-time context object
<%= current_host.endpoint_urls.product %>hostAccount URL for deployed product
<%= access_token %>headersOAuth token when options.oauth is set
<%= app_settings.key %>schema attributesApp settings at runtime

Variable placement rules

Schema attributeAllowed data sources
hostNon-secure iparam, context, current_host.endpoint_urls
pathNon-secure iparam, context
headers (values only)Non-secure iparam, secure iparam (encode), access token, context
queryNon-secure iparam, context

manifest.json declaration

"modules": {
"common": {
"location": {
"full_page_app": { "url": "full_page.html" }
},
"requests": {
"publicGet": {},
"iparamHostGet": {},
"searchTickets": {},
"postWithBody": {},
"withRetryOptions": {}
},
"functions": {
"invokeRequestTemplate": { "timeout": 20 }
}
},
"support_ticket": {
"location": {
"ticket_sidebar": { "url": "sidebar.html" }
}
}
}

Template names must match config/requests.json.


invokeTemplate()

Front-end (HTML surfaces)

client.request.invokeTemplate('publicGet',{context: {host: 'swapi.dev',path: '/api/people/1'},body: JSON.stringify({key: 'value'}),cache: true,ttl: 60000});

Serverless (server.js)

constresult=await$request.invokeTemplate('publicGet',{context: {host: 'swapi.dev',path: '/api/people/1'},body: JSON.stringify({key: 'value'})});

Arguments

ArgumentTypeDescription
requestTemplateNamestring (required)Key in requests.json and manifest
contextobjectVariables for <%= context.* %> substitution
bodystring/objectHTTP request body
cachebooleanFront-end only: cache response in localStorage
ttlnumberCache duration ms when cache is true (default 60000)
options.accountstringOAuth multi-account name (platform v3.1+)

Response object

{
"status": 200,
"headers": { "Content-Type": "application/json;charset=utf-8" },
"response": "{ \"name\": \"Luke\" }"
}
FieldTypeDescription
statusnumberHTTP status from third-party
headersobjectResponse headers
responsestringResponse body (parse JSON as needed)

File upload patterns (reference only)

Object store file upload via request templates is not supported in Freshdesk. The catalog includes reference JSON for:

  • multipart/form-dataformData.fields + formData.files with ref from object store
  • application/octet-streamfile.ref for single-file upload

OAuth pattern (reference)

{
"schema": {
"method": "GET",
"host": "app.asana.com",
"path": "/api/1.0/workspaces",
"headers": {
"Authorization": "bearer <%= access_token %>"
}
},
"options": { "oauth": "asana" }
}

Allow-list IPs

Provide these IPs to third-party APIs when they require IP whitelisting:

RegionIPs
United States18.233.117.211, 35.168.222.30
Germany/Europe-Central18.197.138.225, 52.57.69.21
Sweden/Europe-North13.63.205.168, 13.50.203.236
India13.232.159.149, 13.233.170.242
Australia13.211.182.225, 52.63.187.64
UAE3.29.180.34, 51.112.23.180

Common error codes

StatusMessage / cause
400Invalid URL, substitution failure, whitelist, circuit breaker, response size exceeded
403URL not allowed (blocklist)
415Unsupported response Content-Type
429Rate limit exceeded
502Connection / TLS error
504Request timeout

Circuit breaker: repeated API failures trigger a cool-off period; test requests resume normal traffic when the external API recovers.


TLS troubleshooting

If requests fail with certificate validation errors, fetch the chain with OpenSSL:

openssl s_client -connect example.com:443 -showcerts

Provide missing intermediate certificates via options.security.ca (prefer iparam/app settings over hard-coding).


Testing

npm test
fdk validate

Vitest covers:

  • RequestKit.invokeViaSmi and invokeWithCache argument shapes
  • RequestObjects template keys and substitution catalog completeness
  • server.jsinvokeRequestTemplate handler (loaded via VM to match FDK exports = pattern)

Manual smoke test checklist:

  1. Open Integration Ops Center — run Partner webhook notify → verify JSON response.
  2. Configure iparams — run Account ticket sync and Priority escalation search.
  3. Open a ticket sidebar — confirm ticket # and subject appear; run Notify partner webhook.
  4. Expand Developer playbook — verify schema tables render; run cached lookup twice.
  5. Copy server code from a scenario card — verify clipboard matches sampleCode in request-objects.js.

Reset local installation parameters when re-testing iparams or API key auth:

rm .fdk/store.sqlite
fdk run

Key Learnings

  1. Bodies at invoke time — HTTP request bodies are not part of the template schema; pass body when calling invokeTemplate.
  2. Secure iparam encoding — use encode(iparam.api_key) in Authorization headers; never embed raw secure values in front-end code.
  3. Global app requests — declare templates under modules.common.requests and enable global_apps.enabled.
  4. Scenario-first teaching — cards explain client workflows; the playbook holds raw schema reference (like Agent Huddle's sample notes vs saved notes).
  5. SMI for live drills — scenario cards and Quick Connect route through serverless so API keys stay server-side.
  6. Ticket context in sidebar — webhook and search payloads derive from client.data.get('ticket'), not hard-coded demo values.
  7. Front-end invoke is teaching-only — cached lookup demo lives in the playbook; production integrations should use SMI.
  8. Reference vs live — future-pattern cards document upload/OAuth/TLS JSON not runnable in Freshdesk without object store or OAuth config.

Resources

About

Sample codes to demonstrate making API calls using Request Method

Topics

Resources

Contributing

Stars

9 stars

Watchers

2 watching

Forks

Contributors

Languages