Skip to main content
Flows is currently in beta and is subject to change as the platform evolves
Flows are defined as YAML workflow templates. A Flow template is a YAML document that defines how a workflow runs: what input it accepts, where execution starts, which states it executes, how it branches, when it pauses for additional input, and what output it returns. In familiar terms, Flows follow a workflow-as-code model for orchestrating Sohar APIs. At the top level, a Flow template has five main parts:
  • input: the schema for the data required to start the Flow
  • startsAt: the first state to execute
  • states: the workflow definition
  • output: the shape of the final result returned by the Run
  • metadata: optional fields such as name, description, and version

Template Structure

The input section defines the contract for starting a Run. This is the shape your application must satisfy when it provides inputData. The states section defines the workflow itself. Each state represents a unit of execution, such as calling a Sohar API, making a decision, or waiting for more input. The output section defines the final response shape for the Flow. When a Run completes, the API returns the result of evaluating this output mapping for that specific execution. A minimal template looks like this:
input:
  type: object
  required:
    - patient
  properties:
    patient:
      type: object
      required:
        - firstName
        - lastName
        - dateOfBirth
        - state
      properties:
        firstName:
          type: string
        lastName:
          type: string
        dateOfBirth:
          type: string
        state:
          type: string

startsAt: discovery

states:
  discovery:
    type: request
    resource: Discovery
    resultSelector:
      type: object
      properties:
        payerId:
          type: string
          value: $response.payerId
    next: final

  final:
    end: true

output:
  type: object
  properties:
    payerId:
      type: string
      value: $.payerId

Input

Each Flow template defines the input required to start a Run. This is declared in the template’s input section as a schema. When a Run is created, the inputData provided by the caller must match that schema. In practical terms, the input section defines the contract for using the Flow. It tells you what data must be available at the start of execution, before any states run. For example, a Flow that begins with a Verification request may require input such as patient details, payer information, member ID, place of service code, and specialty code. A Flow that begins with Discovery may require a smaller input shape, such as patient information alone. A simple input definition might look like this:
input:
  type: object
  required:
    - patient
    - payerId
    - memberId
  properties:
    patient:
      type: object
      required:
        - firstName
        - lastName
        - dateOfBirth
        - state
      properties:
        firstName:
          type: string
        lastName:
          type: string
        dateOfBirth:
          type: string
        state:
          type: string
    payerId:
      type: string
    memberId:
      type: string
When designing a Flow, the input should include everything needed to begin execution. In many cases, this means the input shape will mirror the request payload expected by the first Sohar API the Flow calls, or the shared fields needed across multiple later states.

States

Flows currently support three main state types:
  • request
  • choice
  • callback
A state can also be terminal by setting end: true.

Request States

A request state calls a supported Sohar API as part of the workflow. Use request states when you want the Flow to perform work such as creating a Verification, running Discovery, or invoking another supported product operation. A request state defines the resource to call, and it must either specify the next state or mark itself as terminal with end: true. Request states can also control how data moves through the workflow:
  • override lets you adjust the runtime context before the request runs
  • resultSelector lets you map values from the API response back into the Flow context for use in later states
This is the core orchestration mechanism in Flows: each request state turns the template into an executable multi-step API workflow.

Using Result Selector

Use resultSelector when a later step needs data from the API response returned by the request state. For example, a Verification request may return a status that you want to use in a later choice state. In that case, resultSelector can copy the value into the Flow context:
verification:
  type: request
  resource: Verification
  resultSelector:
    type: object
    properties:
      verificationStatus:
        type: string
        value: $response.status
  next: route
After this state runs, $.verificationStatus is available to the rest of the Flow.

Using Override

Use override when a request should run with a modified version of the current runtime context. This is useful when you want to set or replace values for a specific request without changing the original input contract of the Flow. For example, you may want to force a specific payer ID before running a request:
verification:
  type: request
  resource: Verification
  override:
    payerId: "00001"
  next: final
In this example, the request runs with payerId set to “00001” in the effective runtime context for that state.

Choice States

A choice state adds branching logic. Choice states evaluate conditions in order and take the first matching branch. This lets you model workflow logic such as:
  • if required data is present, continue to one step
  • if a result indicates success, take one branch
  • if a result indicates a pending or error condition, take another
If no condition matches, the Flow uses the default branch if one is defined.

Callback States

A callback state pauses the workflow and waits for additional input. Use callback states when a Flow cannot continue with the data available at the start of the Run. This is useful for human-in-the-loop workflows, conditional follow-up collection, or integrations where some information becomes available later. When a Run reaches a callback state, it moves to PENDING. The callback step defines the input contract for the additional data required to continue.

Context

Context is the runtime data available to a Flow as it executes. You can think of it as the working memory for a Run. It begins with the inputData provided when the Run starts, and then evolves as the workflow progresses. At runtime, context is built from:
  • the initial inputData provided when the Run is created
  • any callback input submitted later while the Run is PENDING
  • any values written back into context by a request state’s resultSelector
This means the context for a Run is not static. It starts with the input contract for the template, then accumulates the data needed for later states.

Why Context Matters

Request states execute against the current context. In practice, this means the data in context needs to match the input shape expected by the Sohar API the state is calling. If a request state invokes Verification, the context must contain the fields that Verification expects. If a later state invokes Discovery or Cost Estimate, the context must contain the fields required by those APIs at that point in the workflow. To determine what fields a request state needs in context, refer to the API documentation for the Sohar product that state calls. In general, the context available at that point in the Flow should match the request shape that product expects. For example:
  • a Verification request expects a shape like patient, payerId, memberId, placeOfServiceCode, and specialtyCode
  • a Discovery request expects a shape like patient
Because of this, Flow authors should treat context as the contract between states. Each step should either consume fields already present in context or write the fields that later states will need.

Output

Each Flow template also defines the output returned when a Run completes. This is declared in the template’s output section. Rather than returning the raw response from a single Sohar API, a Flow returns the result of evaluating the template’s output mapping for that specific Run. In practical terms, the output section defines the final response contract for the Flow. It lets you decide which values from the workflow should be exposed to the caller, and how those values should be shaped. A simple output definition might look like this:
output:
  type: object
  properties:
    verificationStatus:
      type: string
      value: $.verificationStatus
    verificationId:
      type: string
      value: $.verificationId
In this example, the completed Run returns an object with verificationStatus and verificationId, regardless of how many states the Flow executed internally to produce those values. When designing a Flow, it is helpful to think of output as the public interface of the completed workflow. The Flow may execute several internal states, but the output should expose only the final data the caller actually needs.

Flow Logic

Choice states are how Flows make decisions at runtime. Each choice evaluates a variable from the runtime context and applies a single operator. Choices are evaluated from top to bottom, and the first match wins. If nothing matches, the Flow uses the default path. If no default is defined, execution fails. Supported operators are:
  • isPresent, isNull
  • isTruthy, isFalsy
  • stringEquals, stringMatches
  • numericEquals, lt, gt, lte, gte
A simple branching example:
route:
  type: choice
  choices:
    - variable: $.verificationStatus
      stringEquals: "complete.eligible"
      next: eligible
    - variable: $.verificationStatus
      stringMatches: "^pending\\."
      next: pending
  default: ineligible