unit U1 — 1 of 5
Validate at the boundary
schema first, before anything costs money
Every automation is a pipe between systems that disagree about what a record looks like. The portal calls it `full_name`, the CRM wants `firstName` and `lastName`, the enrichment API returns `company.domain` and the billing tool expects a `customer_ref` you have to invent. Data shaping is the work of turning what arrived into what the next step needs — and validation is deciding, before any of that, whether what arrived is usable at all.
Put validation at the boundary, immediately after the trigger and before anything else runs. A record that fails should never reach an enrichment call you pay for, let alone a CRM write you have to undo. The order that holds up in production is: validate the raw payload against an explicit schema, normalise it into your own internal shape, enrich it, then write. Each step is cheaper to undo than the one after it, which is the entire reason for that sequence.
Where it breaks: validating late, or validating the shape you hoped for rather than the one that arrived. A flow that maps fields first and checks them afterwards has already spent money and possibly written a row by the time it notices the email is missing. Assert first, in one place, and give the rest of the flow a shape it can trust.
worked example
A boundary validator that rejects before anything downstream can spend money or write a row.
// Code Piece — first step after the trigger, before any enrichment or write
export const code = async (inputs) => {
const p = inputs.payload;
const problems = [];
if (typeof p?.email !== 'string' || !p.email.includes('@')) problems.push('email');
if (typeof p?.company !== 'string' || !p.company.trim()) problems.push('company');
if (p?.dealSize != null && typeof p.dealSize !== 'number') problems.push('dealSize type');
if (problems.length) {
// Quarantine, not crash: the run stays green and the record is reviewable.
return { valid: false, problems, raw: p };
}
// Everything below this line can trust the shape.
return { valid: true, record: p };
};field checklist
- Validate immediately after the trigger, before any paid or writing step.
- Assert the shape that arrives, not the shape you hoped for.
- Keep validation in one place so the rest of the flow can trust the record.
- Order the pipeline validate → normalise → enrich → write.
- Return a quarantine result rather than throwing on a bad record.
common failure — Enriched, written, then found invalid
A lead flow mapped fields, called a paid enrichment API and upserted the CRM before a final step checked whether the email was present. Records without one produced enrichment charges and CRM rows keyed on an empty string, which then collided with each other. Move the assertion to the first step after the trigger: nothing that fails validation should reach a step that costs money or writes data.
check your understanding
Put the stages of a lead pipeline in the order that keeps mistakes cheapest to undo.
- Click the steps below in the order they must run.
next unit opens once this is passed
sandbox validation
The check above confirms you followed the unit. Marking the module COMPLETED takes more: build the automation in your own engine and submit the exported flow and its run evidence, signed, to your unique validation URL. See the module page for that spec.