Flow Creation - Precisely Data Integrity Suite

Data Integrity Suite APIs

Product
Data_Integrity
Spatial_Analytics
Data_Enrichment
geo_addressing_1
Services
Spatial Analytics
Data Enrichment
Geo Addressing
ft:title
Data Integrity Suite APIs
ft:locale
en-US
PublicationType
pt_developer
copyrightfirst
2023
copyrightlast
2026

What is a Flow

A Flow is a JSON-defined execution graph that orchestrates a series of operations (called operators) to process data. Each operator performs a specific task and connects to the next operator, forming a chain of operations.

  • Flow: A collection of interconnected operators forming an execution graph.
  • Operator: A node in the graph that performs a specific operation (transform data, make HTTP calls, branch logic, etc.).
  • Global Context: A JSON object that holds all data during flow execution, accessible to all operators.
  • JSONata: An expression language used for querying and transforming JSON data within operators.
Flow Execution:
  1. Input data is placed in the global context (default key: request).
  2. Execution starts from the operator specified in startOperatorId.
  3. Each operator processes data, modifies the global context, and indicates the next operator.
  4. Execution continues until a termination operator (Return or Fail) is reached.
  5. The final result is extracted and returned.

Flow Structure

A flow definition in JSON consists of the following top-level properties:


{
  "flowId": "unique-flow-identifier",
  "startOperatorId": "first-operator-id",
  "inputDataKey": "request",
  "operators": [
    // Array of operator definitions
      ]
}
      
Table 1. Top-Level Properties
Property Required Type Default Description
flowId Yes String - Unique identifier for the flow
startOperatorId Yes String - ID of the operator where execution begins
inputDataKey No String request Key under which input data is stored in the global context
operators Yes Array - Array of operator definitions
Notes:
  • flowId: Must be unique across your application. Used for identifying and loading flows.
  • startOperatorId: Must match the id of one of the operators in the operators array.
  • inputDataKey: Allows you to customize how input data is accessed. For example, if set to payload, use payload.field instead of request.field in expressions.

Flow Execution with Metadata

Metadata is an optional JSON object that can be passed when executing a flow. It provides contextual information that can be accessed by any operator in the flow through JSONata expressions. Metadata is separate from the input data and is typically used for configuration values, request tracking, user context, feature flags, and environment-specific parameters.

How Metadata Works:
  1. Passed at execution time in the flow execution request.
  2. Available throughout the flow; all operators can access metadata via JSONata expressions.
  3. Immutable during flow execution.
  4. Optional; flows can work without metadata if not required.

Flow Execution Request Structure:


{
  "metadata": {
    "key1": "value1",
    "key2": "value2"
  },
  "input": [
    {
      "data_field1": "data_value1",
      "data_field2": "data_value2"
    },
    {
      "data_field1": "data_value3",
      "data_field2": "data_value4"
    }
  ]
}
      
Table 2. Execution Request Properties
Property Required Type Description
metadata No JSON Object Optional metadata accessible to all operators
input Yes Array of JSON Objects Array of input data objects to be processed
Key Points:
  • The metadata field is optional; you can omit it if not needed.
  • The input field is required and contains an array of input records.
  • Each input record is processed independently by the flow.
  • All input records in the batch share the same metadata.

Accessing Metadata in Flows: Metadata can be accessed in JSONata expressions using the metadata prefix, e.g. metadata.geocodeUrl, metadata.requestId.

Metadata Use Cases:
  • Dataset selection
  • Request tracking
  • Feature flags
  • Configuration parameters

Metadata vs Input Data:

Table 3.
Aspect Metadata Input Data
Purpose Configuration, context, parameters Actual data to be processed
Scope Shared across all input records in a batch Individual to each record
Mutability Immutable during flow execution Transformed and enriched during flow
Access metadata.fieldName request.fieldName (or custom inputDataKey)
Required Optional Required
Use Cases URLs, flags, settings, tracking IDs Business data to process

Example: Complete Flow with Metadata

Execution Request:


{
  "metadata": {
    "datasetType": "Premium",
    "requestId": "req-98765",
    "enableCaching": true
      },
  "input": [
    {
      "addressLines": ["123 Main St"],
      "city": "New York",
      "country": "USA"
    }
  ]
}
      

Flow Definition:


{
  "flowId": "geocode-with-metadata",
  "startOperatorId": "validate_country",
  "inputDataKey": "request",
  "operators": [
    {
      "id": "validate_country",
      "type": "Predicate",
      "description": "Check if country is supported",
      "condition": "$exists(request.country) and request.country != ''",
      "successNode": "prepare_request",
      "failureNode": "country_missing_error"
    },
    {
      "id": "prepare_request",
      "type": "Transform",
      "description": "Build geocode request with metadata parameters",
      "operation": "{'address': request, 'dataset': metadata.datasetType, 'requestId': metadata.requestId}",
      "key": "geocode_request",
      "nextNode": "call_geocode"
    },
    {
      "id": "call_geocode",
      "type": "Post",
      "description": "Call geocoding API using metadata URL",
      "url": "https://api.precisely.com/v1/geocode",
      "headers": "{'Content-Type': 'application/json', 'X-Request-ID': metadata.requestId}",
      "body": "{'addresses': [request], 'preferences': {'customPreferences': {'DATA_OPTION': metadata.datasetType}}}",
      "requiredElements": "responses[0]",
      "key": "geocode_result",
      "nextNode": "check_cache_flag"
    },
    {
      "id": "check_cache_flag",
      "type": "Predicate",
      "description": "Check if caching should be enabled",
      "condition": "metadata.enableCaching = true",
      "successNode": "return_with_cache_info",
      "failureNode": "return_result"
    },
    {
      "id": "return_with_cache_info",
      "type": "Return",
      "resultExpression": "{'result': geocode_result, 'cached': true, 'requestId': metadata.requestId}"
    },
    {
      "id": "return_result",
      "type": "Return",
      "resultExpression": "{'result': geocode_result, 'requestId': metadata.requestId}"
    },
    {
      "id": "country_missing_error",
      "type": "Fail",
      "errorCode": 400,
      "status": "VALIDATION_ERROR",
      "errorMessage": "Country field is required"
    }
  ]
}
      
Best Practices for Metadata:
  • Use metadata for configuration values that may vary between environments.
  • Include tracking identifiers (requestId, correlationId) for debugging.
  • Use metadata for feature flags and conditional behavior.
  • Keep metadata structure consistent across requests.
  • Document expected metadata fields in flow documentation.

Handling Optional Metadata: Always check for existence using $exists(metadata.field) and provide defaults as needed.


$exists(metadata.apiUrl) ? metadata.apiUrl : 'https://default-api.example.com'
$exists(metadata.usePremium) and metadata.usePremium = true
metadata.timeout ? metadata.timeout : 5000
      

Available Operators

The Multipass SDK provides several built-in operators for common operations. Each operator has a specific purpose and set of properties.

  • Simple Operators: Perform operations and proceed to a single next node (Transform, Get, Post)
  • Conditional Operators: Branch execution based on conditions (Predicate)
  • Termination Operators: End flow execution and return results (Return, Fail)

Transform Operator

Purpose: Transform data using JSONata expressions and store the result in the global context.

Use Cases: Extract fields, perform calculations, restructure JSON, combine fields.

Table 4.
Property Required Type Description
id Yes String Unique identifier for this operator
type Yes String Must be "Transform"
operation Yes String JSONata expression that transforms data
key Yes String Key where the transformation result will be stored
nextNode Yes String ID of the next operator to execute
description No String Human-readable description

JSON Example:


{
  "id": "transform_city",
  "type": "Transform",
  "description": "Convert city name to uppercase and trim spaces",
  "operation": "$uppercase($trim(request.city))",
  "key": "normalized_city",
  "nextNode": "next_operator"
}
      

Common JSONata Operations:


"operation": "request.city"
"operation": "$uppercase($trim(request.city))"
"operation": "request.age >= 18 ? 'adult' : 'minor'"
"operation": "$join(request.addressLines, ', ')"
"operation": "{'fullName': request.firstName request.lastName, 'age': request.age}"
"operation": "request.price * 1.1"
      

Get Operator

Purpose: Perform HTTP GET requests to external APIs and store the response in the global context.

Use Cases: Fetch data from REST APIs, retrieve configuration, call external services.

Table 5.
Property Required Type Description
id Yes String Unique identifier for this operator
type Yes String Must be "Get"
url Yes String The URL endpoint for the GET request
key Yes String Key where the HTTP response will be stored
nextNode Yes String ID of the next operator to execute
description No String Human-readable description
urlParams No Array List of URL query parameters
headers No String JSONata expression for HTTP headers
requiredElements No String JSONata expression to extract specific fields from the response
failOnError No Boolean If true, flow fails on HTTP errors (default: true)

Automatic Bearer Token Injection: The Multipass service automatically injects the bearer token from the Authorization header into your input data as request.bearer_token.

JSON Example:


{
  "id": "get_user_data",
  "type": "Get",
  "description": "Fetch user profile from API",
  "url": "https://api.example.com/users",
  "urlParams": [
    {"key": "id", "value": "request.userId"},
    {"key": "include", "value": "'profile,settings'"}
  ],
  "headers": "{'Authorization': 'Bearer ' request.token, 'Accept': 'application/json'}",
  "requiredElements": "data.profile",
  "key": "user_profile",
  "nextNode": "process_user"
}
      

Post Operator

Purpose: Perform HTTP POST requests to external APIs with a request body and store the response.

Use Cases: Submit data to APIs, create or update resources, authenticate, send data for processing.

Table 6.
Property Required Type Description
id Yes String Unique identifier for this operator
type Yes String Must be "Post"
url Yes String The URL endpoint for the POST request
body Yes String JSONata expression for the request body
key Yes String Key where the HTTP response will be stored
nextNode Yes String ID of the next operator to execute
description No String Human-readable description
urlParams No Array List of URL query parameters
headers No String JSONata expression for HTTP headers
requiredElements No String JSONata expression to extract specific fields from the response
failOnError No Boolean If true, flow fails on HTTP errors (default: true)

JSON Example:


{
  "id": "create_user",
  "type": "Post",
  "description": "Create a new user account",
  "url": "https://api.example.com/users",
  "body": "{'email': request.email, 'name': request.name, 'age': request.age}",
  "headers": "{'Content-Type': 'application/json', 'Authorization': 'Bearer 'auth_token}",
  "requiredElements": "data.userId",
  "key": "created_user",
  "nextNode": "return_success"
}
      

Predicate Operator

Purpose: Implement conditional branching logic based on boolean expressions.

Use Cases: Validate input data, route execution, implement business rules, error handling.

Table 7.
Property Required Types Description
id Yes String Unique identifier for this operator
type Yes String Must be "Predicate"
condition Yes String JSONata expression that evaluates to boolean
successNode Yes String ID of the operator to execute if condition is true
failureNode Yes String ID of the operator to execute if condition is false
description No String Human-readable description

JSON Example:


{
  "id": "check_age",
  "type": "Predicate",
  "description": "Check if user is an adult",
  "condition": "request.age >= 18",
  "successNode": "adult_flow",
  "failureNode": "minor_flow"
}
      

Return Operator

Purpose: Terminate the flow successfully and return data to the caller.

Use Cases: Return processed results, success responses, end flow execution.

Table 8. Return Operator Properties
Property Required Type Description
id Yes String Unique identifier for this operator
type Yes String Must be "Return"
resultExpression Yes String JSONata expression specifying what data to return
description No String Human-readable description

JSON Example:


{
  "id": "return_result",
  "type": "Return",
  "description": "Return the processed user data",
  "resultExpression": "processed_user"
}
      

Fail Operator

Purpose: Terminate the flow with an error state.

Use Cases: Handle validation failures, report errors, terminate on unrecoverable conditions.

Table 9.
Property Required Type Description
id Yes String Unique identifier for this operator
type Yes String Must be "Fail"
description No String Human-readable description
errorCode No Integer HTTP-style error code (default: 500)
status No String Custom status string
errorMessage No String Error message to return

JSON Example:


{
  "id": "validation_failed",
  "type": "Fail",
  "description": "Input validation failed",
  "errorCode": 400,
  "status": "VALIDATION_ERROR",
  "errorMessage": "Required field 'email' is missing"
}
      

Error Handling in Flows

Understanding how errors propagate through flows and implementing proper error handling is crucial for building robust workflows.

How Errors Propagate:
  • HTTP Operators (Get/Post): By default, HTTP errors (4xx, 5xx) will fail the flow. Use failOnError: false to continue execution even on HTTP errors.
  • Transform Operators: JSONata expression errors will fail the flow.
  • Predicate Operators: Condition evaluation errors will fail the flow.
  • Fail Operators: Explicitly terminate flow with error.

Error Handling Patterns: See the original guide for detailed JSON examples of error handling, fallback, retry logic, validation chains, and error enrichment.

JSONata Expressions

JSONata is a powerful query and transformation language for JSON data. It's used extensively in Multipass flows.

Common JSONata Functions:
  • String: $uppercase(), $lowercase(), $trim(), $contains()
  • Numeric: $number(), $round(), $sum()
  • Array: $count(), $exists(), $append()
  • Object: $keys(), $merge()
  • Date/Time: $now(), $fromMillis()

Accessing Data in Expressions: Use request.field for input data, metadata.field for metadata, and $ for the entire global context.

Expression Validation: Always validate your JSONata expressions before deploying flows. Use the JSONata Exerciser to test expressions with sample data.

Complete Flow Examples

See the original guide for detailed JSON examples of flows for data transformation, API integration, multi-step orchestration, error handling, and metadata usage.

Best Practices

Flow Design: Use descriptive IDs, add descriptions, keep flows focused, plan error handling, avoid circular references.

JSONata Expressions: Test expressions, use readable code, handle nulls, avoid complexity.

Error Handling: Validate input early, provide meaningful error messages, use appropriate codes, document failure scenarios.

Metadata Usage: Use for configuration, tracking, feature flags; keep structure simple; check for existence; do not store sensitive data.

API Integration: Store tokens, use requiredElements, set headers, handle errors.

Batch Processing: Use metadata for batch-level config, design flows to be stateless, do not access other records' results.

Performance: Minimize HTTP calls, reuse computed values, cache data when possible.

Maintenance: Version flows, document logic, test with various inputs, keep under version control.

Naming Conventions: Use verb_noun for operator IDs, descriptive nouns for keys, kebab-case for flow IDs.

Testing: Test all branches, error paths, with/without metadata, batch processing.

API Usage Summary

Creating a Flow: POST /v1/multipass/flows/{flowId}

Retrieving a Flow: GET /v1/multipass/flows/{flowId}

Executing a Flow: POST /v1/multipass/flows/{flowId}/execute

Updating a Flow: PUT /v1/multipass/flows/{flowId}

Deleting a Flow: DELETE /v1/multipass/flows/{flowId}

Listing All Flows: GET /v1/multipass/flows

Key Points: Authentication required, metadata is optional, batch processing supported, request tracking via X-Request-ID, always use application/json, flows are cached, API returns appropriate status codes.

Quick Reference Card

Table 10. Operator Summary
Operator Purpose Next Node Key Properties
Transform Transform data with JSONata Single (nextNode) operation, key
Get HTTP GET request Single (nextNode) url, key
Post HTTP POST request Single (nextNode) url, body, key
Predicate Conditional branching Two (successNode, failureNode) condition
Return Successful termination None (ends flow) resultExpression
Fail Failed termination None (ends flow) errorCode, errorMessage

Additional Resources