Guides
Build a workflow
Automate actions with code workflows
Code workflows let you run JavaScript when records change — validate fields, update related records, send notifications, or sync data.
How workflows work
- A record is added to a list (trigger)
- Clarify runs your JavaScript code block
- Your code reads the record, makes decisions, and writes back via the API
Your code receives an input object with:
input.record— the record that triggered the workflowinput.diff— array of field changes, each withop,path,val, andoldValinput.actor— who/what made the changeinput.workspace— your workspace slugprocess.env.CLARIFY_API_KEY— your workspace API key (available as an env var)
Example: validate required fields on stage change
This workflow checks that required fields are filled when a deal moves to "Closed Won", and reverts the stage if they're not:
var record = input.record;
var diff = input.diff;
// Skip if triggered by another workflow (prevent loops)
if (input.actor.source_id === "workflow" || input.actor.entity === "api_key") {
return;
}
// Only run when stage changes to Closed Won
if (record.stage !== "Closed Won") {
return;
}
var errors = [];
if (!record.amount) errors.push("Amount is required");
if (!record.close_date) errors.push("Close date is required");
if (!record.company_id) errors.push("Company is required");
if (errors.length > 0) {
// Find the old stage value from the diff array
var stageChange = diff.find(function(d) { return d.path === "stage"; });
var oldStage = stageChange ? stageChange.oldVal : "Negotiation";
await fetch(
"https://api.clarify.ai/v1/workspaces/" + input.workspace + "/objects/deal/records",
{
method: "PATCH",
headers: {
"Authorization": "api-key " + process.env.CLARIFY_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
data: [{
id: record._id,
type: "deal",
attributes: {
stage: oldStage,
validation_error_notes: errors.join(", ")
}
}]
})
}
);
}Key patterns
Loop guard
Every workflow that writes data must check the actor to prevent infinite loops:
if (input.actor.source_id === "workflow" || input.actor.entity === "api_key") {
return;
}Fetching the full record
The trigger payload may not include all fields. Fetch the full record if you need fields beyond what's in the diff:
var res = await fetch(
"https://api.clarify.ai/v1/workspaces/" + input.workspace + "/objects/deal/records/" + record._id,
{
headers: { "Authorization": "api-key " + process.env.CLARIFY_API_KEY }
}
);
var full = await res.json();
var deal = full.data.attributes;Writing validation errors
Instead of creating tasks, write plain-language errors to a text field on the record. Customers prefer this pattern:
// Write error to a text field on the record
{ validation_error_notes: "Amount and close date are required" }
// Clear on success
{ validation_error_notes: "" }Tips
- Use
varinstead ofconst/letfor broader compatibility in the runtime - Test with a single record before enabling for your full pipeline
- Workflows trigger on list membership — make sure your list filter matches the right records