Skip to main content
Service Bridges allow you to configure proxy endpoints that connect your project to external APIs. They enable modules and the platform to interact with external services through a managed, authenticated gateway. Service Bridges grid showing configured bridges with names, target URLs, and status

What are Service Bridges?

A service bridge creates a proxy endpoint within the Kodexa platform that forwards requests to an external API. This provides:
  • Centralized authentication — API credentials are managed as organization secrets, not embedded in modules. The platform supports automatic OAuth token management.
  • Request routing — Modules reference a bridge endpoint rather than external URLs directly
  • Caching — Responses can be cached per-endpoint with configurable TTL
  • Request/response transformation — JavaScript hooks can modify requests before sending and responses before returning
  • Monitoring — All requests through bridges are logged and can be monitored

Managing Service Bridges

Creating a Service Bridge

1

Click Add Service Bridge

Open the creation form from the Service Bridges page.
2

Configure Endpoint

Set the bridge name, target URL, authentication method, and any required headers.
3

Test Connection

Verify that the bridge can reach the external API.
4

Save

The bridge endpoint becomes available for use in your project’s modules and pipelines.
Service Bridge creation form showing name, target URL, and authentication configuration
Service bridges use organization secrets for authentication credentials. Make sure the required secrets are configured before creating a bridge that needs them.

YAML Configuration Reference

Service bridges are defined in YAML and deployed with kdx sync. Here is the full structure:
type: serviceBridge
slug: my-bridge
orgSlug: my-org
name: "My External API"
template: false
publicAccess: false

metadata:
  baseUrl: "https://api.example.com"       # Supports ${secrets.X} interpolation
  description: "Connects to the example API"
  provider: "Example Corp"

  # Authentication (see below for details)
  auth:
    type: oauth2_client_credentials
    tokenUrl: "/v1/auth/token"              # Relative to baseUrl, or absolute
    clientId: "${secrets.MY_CLIENT_ID}"
    clientSecret: "${secrets.MY_CLIENT_SECRET}"

  defaultHeaders:
    - name: "Content-Type"
      value: "application/json"

  endpoints:
    - name: "get-data"
      description: "Fetch data from the API"
      path: "/v1/data"
      method: GET
      cacheEnabled: true
      cacheTtlSeconds: 300

Secret References

Use ${secrets.SECRET_NAME} to reference organization secrets in your bridge configuration. The platform resolves these at request time. This works in:
  • baseUrl
  • auth.clientId, auth.clientSecret, auth.tokenUrl
  • Header values
metadata:
  baseUrl: "${secrets.MY_API_BASE_URL}"
  auth:
    clientId: "${secrets.MY_CLIENT_ID}"
    clientSecret: "${secrets.MY_CLIENT_SECRET}"

Authentication

OAuth 2.0 Client Credentials

The platform can automatically manage OAuth 2.0 client credentials token lifecycle — acquiring tokens, caching them, and refreshing on expiry. This eliminates the need for external token rotation.
metadata:
  auth:
    type: oauth2_client_credentials
    tokenUrl: "/v1/auth/token"
    clientId: "${secrets.CLIENT_ID}"
    clientSecret: "${secrets.CLIENT_SECRET}"
The platform will:
  1. Fetch a token from the token endpoint on the first request
  2. Cache the token until near expiry
  3. Automatically refresh when the token expires
  4. Retry once with a fresh token if the upstream API returns 401 or 403

Standard vs Custom Token Requests

Most OAuth providers use the standard form-encoded format (RFC 6749). The platform uses this by default:
POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=...&client_secret=...
If your token endpoint expects a custom JSON body, use requestFormat: custom:
metadata:
  auth:
    type: oauth2_client_credentials
    tokenUrl: "/v1/auth/token"
    clientId: "${secrets.CLIENT_ID}"
    clientSecret: "${secrets.CLIENT_SECRET}"
    requestFormat: custom
    requestBody:
      grantType: "client_credentials"
      clientId: "${auth.clientId}"
      clientSecret: "${auth.clientSecret}"
The ${auth.clientId} and ${auth.clientSecret} placeholders in requestBody are substituted with the resolved values from the auth block.

Custom Response Mapping

If the token endpoint returns non-standard field names, use responseMapping:
metadata:
  auth:
    responseMapping:
      accessToken: "accessToken"     # Default: "access_token"
      expiresIn: "expiresIn"         # Default: "expires_in"

Full Auth Configuration Reference

FieldTypeDefaultDescription
typestringrequiredAuthentication type. Currently oauth2_client_credentials.
tokenUrlstringrequiredToken endpoint URL. Relative paths are resolved against baseUrl.
clientIdstringrequiredOAuth client ID. Supports ${secrets.X}.
clientSecretstringrequiredOAuth client secret. Supports ${secrets.X}.
requestFormatstring"standard""standard" (form-encoded) or "custom" (JSON body).
requestBodyobjectCustom JSON body template when requestFormat is "custom".
responseMappingobjectMaps non-standard token response field names.
tokenCacheBufferSecondsinteger60Seconds before expiry to refresh the token.
headerNamestring"Authorization"HTTP header for the token.
headerPrefixstring"Bearer"Prefix prepended to the token value.

Static API Key / Bearer Token

For APIs that use a static API key or pre-generated token, set it directly in headers using a secret reference:
metadata:
  defaultHeaders:
    - name: "Authorization"
      value: "Bearer ${secrets.MY_API_TOKEN}"
    - name: "X-API-Key"
      value: "${secrets.MY_API_KEY}"

Endpoints

Each endpoint defines a path on the external API that the bridge exposes.
endpoints:
  - name: "get-users"                  # Used in serviceBridge.call()
    description: "List all users"
    path: "/v1/users"                  # Appended to baseUrl
    method: GET
    cacheEnabled: true                 # Cache GET responses
    cacheTtlSeconds: 600               # Cache for 10 minutes

Request and Response Schemas

Optionally document the expected request and response shapes using JSON Schema:
endpoints:
  - name: "create-user"
    path: "/v1/users"
    method: POST
    requestSchema:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
      required:
        - name
        - email
    responseSchema:
      type: object
      properties:
        id:
          type: string
        name:
          type: string

Script Hooks

Endpoints support JavaScript hooks for request/response transformation:
HookRunsInputCan Return
initScriptOnce per request (when no client context){headers, config}{headers, context}
preSendScriptBefore each outbound call{headers, body, context}{headers, body}
postReplyScriptAfter each response{statusCode, body}{body}
endpoints:
  - name: "lookup"
    path: "/v1/lookup"
    method: POST
    postReplyScript: |
      var data = JSON.parse(input.body);
      var options = data.map(function(item) {
        return { label: item.name, value: item.code };
      });
      return { body: JSON.stringify(options) };

Using Service Bridges from Script Steps

Service bridges that are added as project resources can be called directly from script steps in plan workflows. Scripts can discover available bridges with serviceBridge.list() and make HTTP requests with serviceBridge.call().
// List all bridges available to this project
var bridges = serviceBridge.list();

// Call an endpoint
var result = serviceBridge.call("my-bridge", "get-data");
log("info", "Response: " + JSON.stringify(result));

return { action: "done" };
See the Script Steps guide for full documentation on using service bridges from scripts.

Using Service Bridges from Data Forms

Data forms can call service bridge endpoints both declaratively and from scripts:

Declarative (Selection Options)

In taxonomy definitions, use selectionOptionFormula to populate dropdowns:
selectionOptionFormula: 'serviceBridgeCall("my-org/my-bridge", "get-options")'
With parameters:
selectionOptionFormula: 'serviceBridgeCall("my-org/my-bridge", "get-options", "paramName", {fieldPath})'

From Data Form Scripts

var result = await bridge.serviceBridge.call(
  'my-org/my-bridge',
  'get-data',
  { id: fv['shipments/code'] }
);

Loading Shared Modules in Bridge Scripts

Service bridge endpoint scripts can load shared JavaScript modules using the Module Refs picker in the endpoint configuration. Pre-loaded modules’ functions and variables are available in global scope within your bridge script, letting you reuse request/response transformation logic across endpoints. Select one or more JavaScript modules from your organization. They are fetched and executed in order before your bridge script runs.
// Assuming "my-org/transform-utils" is loaded via Module Refs
var payload = transformRequest(request);
var result = serviceBridge.call("external-api", "submit", payload);
return formatResponse(result);