Portal Community

Full Node Config

{
  "nodeType": "BusinessServiceCall",
  "config": {
    "serviceId": "hr-service",
    "operationId": "updateLeaveBalance",
    "inputMap": {
      "employeeId": "$output.fetchEmployee.employeeId",
      "leaveType": "$json.leaveType",
      "daysToDeduct": "$output.approvalResult.approvedDays",
      "reason": "\"Approved leave request\""
    },
    "pathParams": {
      "employeeId": "$output.fetchEmployee.employeeId"
    },
    "timeoutSeconds": 15
  }
}

Input Map Evaluation

The inputMap values are expressions evaluated in the parent context before the service call. The result is the request body sent to the service:

[NodeCapability(CapabilityType.BusinessService)]
public class BusinessServiceCallExecutor : BaseNodeExecutor
{
    public override async Task<NodeExecutionResult> ExecuteAsync(NodeExecutionContext ctx)
    {
        var config = ctx.GetConfig<BusinessServiceCallConfig>();

        // Resolve endpoint
        var endpoint = await _registry.ResolveEndpointAsync(config.ServiceId, config.OperationId);

        // Substitute path params
        foreach (var (key, expr) in config.PathParams ?? new())
            endpoint = endpoint.Replace($"{{{key}}}", ctx.EvaluateExpression<string>(expr));

        // Build request body from inputMap
        var body = config.InputMap.ToDictionary(
            kv => kv.Key,
            kv => ctx.EvaluateExpression<object>(kv.Value));

        // Get auth headers
        var auth = await _authProvider.GetAuthHeadersAsync(config.ServiceId);

        // Make the call
        var response = await _httpClient.PostAsJsonAsync(endpoint, body, auth);
        var result = await response.Content.ReadFromJsonAsync<object>();

        return NodeExecutionResult.Success(result);
    }
}

GET Operations with Path Params

For GET operations, the inputMap becomes query parameters and pathParams are substituted in the URL:

{
  "serviceId": "hr-service",
  "operationId": "getPayHistory",
  "pathParams": {
    "employeeId": "$output.fetchEmployee.employeeId"
  },
  "inputMap": {
    "fromDate": "$json.fromDate",
    "toDate": "$json.toDate",
    "limit": "10"
  }
}
// Resolves to: GET /api/v2/employees/emp-001/pay-history?fromDate=...&toDate=...&limit=10