--- url: https://developer-portal.gainsight.com/docs/connectors/how-connectors-work.md description: >- How the connector pipeline processes requests and responses — parameter merging, variable resolution, secret injection, authentication, and payload transformation --- # How Connectors Work A **connector** is a server-side proxy that sits between your widget and an external API. Every connector request passes through a pipeline of processing stages before reaching the destination, and the response passes through its own pipeline before returning to your widget. ## The pipeline ```mermaid flowchart TD W["Widget (Browser)"]:::endpoint subgraph req ["Request Pipeline"] direction TB S1["Merge Params & Headers"]:::request S2["Resolve Template Variables
user.*, tenant_id"]:::request S3["Inject Secrets"]:::request S4["Apply Authentication"]:::request S5["Request Payload Transformation"]:::request S6["Cache Lookup"]:::request S1 --> S2 --> S3 --> S4 --> S5 --> S6 end S6 -->|"Cache hit"| W S6 -->|"Cache miss"| API API["External API"]:::endpoint API --> S7["Response Payload
Transformation"]:::response S7 --> W classDef endpoint fill:#fef3c7,stroke:#f59e0b,color:#1e293b classDef request fill:#dbeafe,stroke:#3b82f6,color:#1e293b classDef response fill:#dcfce7,stroke:#22c55e,color:#1e293b ``` ## Request pipeline Each stage runs in order before the HTTP request leaves the platform. **Merge Params & Headers** — The platform combines the connector's configured headers and query parameters with any overrides sent from the widget code. Fields marked as non-overridable cannot be changed by the browser. See [Headers & Query Parameters](headers-and-query-parameters). Connectors can also declare **path parameters** — values the widget supplies per call that get substituted into {{ pathParams.X }} URL template references. See [Dynamic URL Path Segments](dynamic-url-paths). **Resolve Template Variables** — Template expressions like {{ user.id }} and {{ tenant\_id }} are replaced with values from the authenticated session. These values are resolved on the server — the browser cannot see or tamper with them. See [Template Variables](template-variables) and [Passing User Context](passing-user-context). **Inject Secrets** — Expressions like {{ get\_secret('api\_key') }} in headers, query parameters, and authentication fields are replaced with encrypted secret values. Secrets are never exposed to the browser. See [Secrets and Variables](secrets/). **Apply Authentication** — The platform applies the configured authentication method — adding an API key header, exchanging OAuth credentials for a token, or signing a JWT. See [Authentication](authentication). **Request Payload Transformation** — If a request transformation is configured, the request body is transformed before sending. This lets you reshape data from the widget into the format the external API expects. See [Request Transformation](payload-template). **Cache Lookup** — For GET and HEAD requests, the platform checks whether a cached response exists before calling the external API. On a cache hit, the cached response is returned directly — the external API is never called. On a cache miss, the request proceeds to the external API and the response is stored for future requests. See [HTTP Caching](http-caching). ## Response pipeline After the external API responds (on a cache miss), the response passes through one stage before returning to the widget. **Response Payload Transformation** — If a response template is configured, the response body is transformed before returning to the widget. This lets you filter, reshape, or reformat the API's response. See [Response Transformation](response-transformation). ## Response timeout Once the request leaves the platform, the external API has 15 seconds to respond. If it does not respond in time, the platform abandons the call and the widget's request fails with `502`, carrying a JSON error envelope whose `errors.scope` is `Downstream (network/external service)`. For a composite connector, that scope is prefixed with the name and index of the step that failed. ## Where data belongs Different types of data enter the pipeline at different points. Use this decision tree to determine where a value should be configured. ```mermaid flowchart TD Q{"What kind of data
are you passing?"} Q -->|"API key, password,
token, client secret"| S Q -->|"User ID, email,
name, tenant ID"| CV Q -->|"Search term, filter,
page number, sort order"| B S["Secrets
Encrypted, server-side only"]:::secrets CV["Connector Config
Resolved from authenticated session"]:::config B["Widget Code
Passed via SDK queryParams"]:::browser S --- S2["get_secret('api_key')"]:::example CV --- CV2["user.id, user.email, tenant_id"]:::example B --- B2["queryParams: { q: 'search term' }"]:::example style Q fill:#eef5fc,stroke:#39a2ff,color:#132436 classDef secrets fill:#dbeafe,stroke:#3b82f6,color:#1e293b classDef config fill:#dcfce7,stroke:#22c55e,color:#1e293b classDef browser fill:#fef3c7,stroke:#f59e0b,color:#1e293b classDef example fill:#f8fafc,stroke:#94a3b8,color:#475569 ``` See [Passing User Context](passing-user-context) for the rule on when a value must come from the server rather than the browser, [Secrets and Variables](secrets/) for credential storage, and [Calling from Widget Code](calling-from-widgets) for SDK parameters. ## Next Steps * [Build Your First Connector](build-first-connector) — Hands-on tutorial to create and call a connector * [Passing User Context](passing-user-context) — Securely inject user identity into requests * [Template Variables](template-variables) — Full reference of variables, filters, and functions