How to Build a Reusable Data-Validation Subworkflow for Inbound Payloads

Build one validation workflow in Spojit that checks email, phone, and schema shape, then call it from any inbound-data workflow before you write records to your systems.

What This Integration Does

When data arrives from a form, a partner feed, or a third-party webhook, it is rarely clean. A blank email, a malformed phone number, or a missing required field will happily flow downstream and create a broken customer, a failed order, or a corrupt database row. This tutorial centralizes those checks into a single reusable workflow so you write the rules once and reuse them everywhere. Any inbound-data workflow calls this validator with a Subworkflow node, hands it a raw payload, and gets back a clean pass or fail verdict plus a list of problems before a single record is created.

The validator runs as its own workflow with a Webhook trigger, so it can be invoked both as a Subworkflow step and directly over HTTP for testing. It accepts a JSON payload, runs each field through the validation and json connectors, and returns a structured result of the shape { valid, errors }. It writes nothing to your systems and holds no state: each call is independent, so re-running it on the same payload always returns the same verdict. Because changes to the child take effect immediately for every parent, fixing or tightening a rule once updates every inbound workflow that calls it.

Prerequisites

  • A Spojit workspace where you can create workflows and add nodes on the canvas.
  • A signing connection for the validator's Webhook trigger. The built-in http, json, and validation connectors are utility connectors that run in-process and need no authentication, so no API keys are required.
  • An agreed payload contract: the field names and types your inbound workflows send (for example email, phone, name, country).
  • At least one inbound-data workflow that currently writes records (to a CRM, a database, or an e-commerce store) and that you want to guard.

Step 1: Create the validator workflow with a Webhook trigger

Create a new workflow named validate-inbound-payload. Add a Trigger node and set its type to Webhook. Pick a signing connection (the Spojit scheme is fine for an internal validator). The trigger's output is the parsed JSON body, available as {{ input }}. When this workflow is later called as a Subworkflow, the parent's Input becomes that same {{ input }} object, so a single trigger serves both invocation paths. A representative inbound payload looks like this:

{
  "email": "Jane.Doe@Example.com ",
  "phone": "+61 400 123 456",
  "name": "Jane Doe",
  "country": "AU"
}

Step 2: Confirm required fields with the json connector

Add a Connector node in Direct mode, choose the json connector, and select the get tool. Run it once per required field to read the value out of the payload, for example with path email against input {{ input }}, and save each result to its own output variable such as email_value. A missing field returns an empty result, which you check in the next step. For a stricter shape test, add a second json node using the validate tool to confirm the payload parses as the JSON object you expect before any field-level checks run.

Step 3: Validate the email and phone fields

Add a Connector node in Direct mode, choose the validation connector, and select the email tool. Pass {{ email_value }} as the value to check, and save the result to email_check. Add a second validation node using the phone tool against {{ input.phone }}, saving to phone_check. The validation connector also offers numeric, alphanumeric, url, iso-date, uuid, and is-empty, so you can add a check for every field in your contract. Use is-empty on each required field captured in Step 2 to catch blanks, since an empty string can still pass some format checks.

Step 4: Collect the errors with Condition and json nodes

For each check, add a Condition node that branches on whether the validation result is false. On the failing branch, add a Connector node in Direct mode using the json connector with the set tool to append a human-readable message into an errors array, for example setting an entry like "email is not a valid address". Keep the messages specific so the calling workflow can show or log exactly what failed. After all checks, use the json connector's keys or values tool on the assembled errors object so you have a clean list to return. If you would rather express the assembly as one expression, a single Transform node can build the same errors array from the individual *_check variables.

Step 5: Build the final verdict and return it

Add a Transform node that produces the contract result object. Set valid to true only when every check passed and the error list is empty, and attach the collected list as errors:

{
  "valid": {{ errors.length }} == 0,
  "errors": {{ errors }},
  "checked": {
    "email": {{ email_check }},
    "phone": {{ phone_check }}
  }
}

Add a Response node and return this object so direct HTTP callers receive the verdict synchronously. The same final value is what the parent receives when this workflow runs as a Subworkflow, so both callers see an identical { valid, errors } shape. Save the workflow.

Step 6: Call the validator from an inbound workflow

Open the inbound-data workflow you want to guard. After its trigger and before any node that writes a record, add a Subworkflow node. Set Workflow to validate-inbound-payload and set Input to the raw payload, for example {{ input }} for a webhook-triggered workflow. The parent pauses while the child runs through its own trigger and nodes, and the child's final output returns to the parent (available on the Subworkflow node's output variable, for example {{ validation_result }}).

Step 7: Gate the record write on the verdict

Add a Condition node immediately after the Subworkflow node that branches on {{ validation_result.valid }}. On the true branch, continue to your existing write step (your CRM, database, or e-commerce connector). On the false branch, add a Send Email node to notify the data owner, setting the body to include {{ validation_result.errors }} so the recipient sees exactly which fields failed. This keeps every inbound workflow honest: nothing reaches your systems unless the shared validator says it is clean. To enrich the verdict with a plain-language summary, ask Miraxa, the intelligent layer across your automation, to add a Connector node in Agent mode that turns {{ validation_result.errors }} into a friendly sentence.

Tips

  • Keep the validator's output contract stable. Parents depend on { valid, errors }, so add new fields rather than renaming existing ones.
  • Use Direct mode for every check. The validation and json connectors are deterministic and cost no AI credits, so a payload with twenty checks still runs cheaply.
  • Normalize before you validate: a Transform or the text connector's trim and case tools can lower-case and trim an email so a trailing space does not cause a false failure.
  • Group independent checks under a Parallel node so email, phone, and schema validation run concurrently and the validator returns faster.

Common Pitfalls

  • Empty strings pass format checks. Pair every format tool with the validation connector's is-empty tool, or your required-field guard will leak blanks downstream.
  • Phone formats vary by country. The phone tool is permissive, so if you need a strict national format add a regex connector test step alongside it.
  • Mismatched input keys silently produce empty values. Confirm the parent's Subworkflow Input keys match the field names the validator reads with the json get tool.
  • A child that errors halts the parent. Keep the validator side-effect free so a re-run is always safe, and let the parent's Condition node, not an exception, drive the reject path.

Testing

Before wiring it into production workflows, test the validator on its own. Use its Webhook trigger URL to POST one known-good payload and confirm it returns { "valid": true, "errors": [] }, then POST a payload with a bad email and a blank name and confirm valid is false with two specific messages. Check the execution history: the child appears as its own entry, so you can open it and see exactly which check failed. Once the verdicts look right, add the Subworkflow node to one inbound workflow, run it against a small batch with the record-write step temporarily on the false branch, and only flip the gate live once the pass and reject branches behave as expected.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.