> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Service Bridge Steps in Activity Plans

> Use BRIDGE_CALL steps in Activity Plans to call external systems through service bridges with first-class status, retries, logs, and audit trails.

A `BRIDGE_CALL` step calls a configured Service Bridge from an Activity Plan. It is the right tool when an external system call is part of the business process and should have its own status, result, logs, retry behavior, and audit trail.

Service Bridges keep authentication, target URLs, request rules, caching, and endpoint configuration outside of the Activity Plan. The Activity Plan references the bridge and endpoint, then supplies the request data for this workflow.

## When to Use a BRIDGE\_CALL Step

Use a `BRIDGE_CALL` step when you need to:

* Validate extracted data against a system of record
* Fetch enrichment data before review
* Post approved data to an ERP, loan origination, claims, KYC, or compliance system
* Notify an external workflow when a Kodexa Activity completes
* Keep the external call visible as its own monitored workflow step

Use `serviceBridge.call()` inside a [SCRIPT step](/guides/activity-plans/script-steps) when the bridge call is only one part of a larger custom decision.

## Step Configuration

```json theme={null}
{
  "slug": "post-approved-invoice",
  "kind": "BRIDGE_CALL",
  "dependsOn": ["analyst-review:approved"],
  "config": {
    "serviceBridgeRef": "finance-erp",
    "endpointName": "post-invoice",
    "requestBody": {
      "documentFamilyId": "{{inputs.documentFamilyId}}",
      "sourceSystem": "{{inputs.sourceSystem}}"
    },
    "treatAsError": "$.status != 'accepted'",
    "timeoutSeconds": 30,
    "disableCache": true
  }
}
```

| Config key         | Description                                                       |
| ------------------ | ----------------------------------------------------------------- |
| `serviceBridgeRef` | Service Bridge slug or ref                                        |
| `endpointName`     | Endpoint defined by the bridge                                    |
| `requestBody`      | Static body, template, or expression that builds the JSON request |
| `requestQuery`     | Optional query-string template                                    |
| `requestPath`      | Optional path substitution                                        |
| `requestHeaders`   | Optional request headers, excluding secrets                       |
| `requestScript`    | Optional JavaScript preprocessor for complex request construction |
| `bridgeActions`    | Actions the bridge response can emit for downstream routing       |
| `treatAsError`     | Predicate that marks a response as a failed step                  |
| `timeoutSeconds`   | Per-call timeout                                                  |
| `disableCache`     | Whether to bypass bridge-level caching for this call              |

## How It Runs

```mermaid theme={null}
sequenceDiagram
    participant Activity
    participant BridgeStep as BRIDGE_CALL step
    participant KodexaAPI as Kodexa API
    participant External as External system
    Activity->>BridgeStep: Start step with inputs
    BridgeStep->>KodexaAPI: Resolve serviceBridgeRef and endpointName
    KodexaAPI->>KodexaAPI: Inject configured auth and request rules
    KodexaAPI->>External: Send request
    External-->>KodexaAPI: Response
    KodexaAPI-->>BridgeStep: Parsed result
    BridgeStep-->>Activity: Complete, fail, or emit action
```

The step result is stored on the Activity step. Operators can inspect the response, failure details, and logs without digging through a script.

## Request Mapping

Start with a static JSON body when possible:

```json theme={null}
{
  "requestBody": {
    "documentFamilyId": "{{inputs.documentFamilyId}}",
    "projectId": "{{project.id}}"
  }
}
```

Use `requestScript` when the request needs conditional shaping:

```json theme={null}
{
  "requestScript": "return { invoiceId: inputs.invoiceId, amount: Number(inputs.amount || 0), urgent: Number(inputs.amount || 0) > 10000 };"
}
```

Keep request scripts small. If you need several external calls or substantial document mutation, use a SCRIPT step.

## Response Routing

A bridge call can emit actions so downstream steps depend on the external response.

```json theme={null}
{
  "slug": "validate-supplier",
  "kind": "BRIDGE_CALL",
  "config": {
    "serviceBridgeRef": "finance-reference-data",
    "endpointName": "validate-supplier",
    "requestBody": {
      "supplierId": "{{inputs.supplierId}}"
    },
    "bridgeActions": [
      {
        "name": "valid",
        "when": "$.valid = true"
      },
      {
        "name": "review",
        "when": "$.valid != true"
      }
    ]
  }
}
```

Then route downstream work:

```json theme={null}
{
  "slug": "supplier-review",
  "kind": "CREATE_TASK",
  "dependsOn": ["validate-supplier:review"],
  "config": {
    "taskTemplateRef": "supplier-exception-review"
  }
}
```

## Error Handling

Use `treatAsError` when a successful HTTP response should still fail the step.

```json theme={null}
{
  "treatAsError": "$.status = 'rejected' or $.error != null"
}
```

The Activity can then be retried from the failed step after the upstream issue is fixed.

Design bridge calls to be idempotent. Activities can be retried, and triggers can fire more than once in at-least-once workflows. External endpoints should tolerate duplicate request IDs or use a stable idempotency key from Activity inputs.

## Security and Binding

Service Bridges are project resources. A `BRIDGE_CALL` step can only use bridges that are available to the project running the Activity.

This gives the platform a clear boundary:

* The Activity Plan defines the workflow.
* The project binding defines which bridges are allowed.
* The bridge configuration owns authentication and endpoint details.
* The step owns request data, routing, and result handling for this business process.

Do not put secrets in Activity Plan step config. Use Service Bridge authentication settings and organization secrets instead.

## BRIDGE\_CALL vs SCRIPT with serviceBridge.call()

| Requirement                                                       | Better fit    |
| ----------------------------------------------------------------- | ------------- |
| One external call should be visible and retryable as its own step | `BRIDGE_CALL` |
| Several external calls feed one custom decision                   | `SCRIPT`      |
| Request mapping is straightforward                                | `BRIDGE_CALL` |
| The call should mutate documents before deciding the branch       | `SCRIPT`      |
| Operators need to see the external call status directly           | `BRIDGE_CALL` |

## Next Steps

<CardGroup cols={2}>
  <Card title="Activity Plan Steps" icon="diagram-project" href="/guides/activity-plans/steps">
    See how bridge steps fit with CREATE\_TASK, SCRIPT, EXECUTION, and LLM steps.
  </Card>

  <Card title="Calling Service Bridges from Scripts" icon="plug" href="/guides/scripting/service-bridges">
    Use `serviceBridge.call()` from scripts, formulas, and event subscriptions.
  </Card>
</CardGroup>
