Turn a Clay Routine Result into the Next Automation Step
Turn a Clay Routine Result into the Next Automation Step
Yes. A workflow tool can pass the result of an automated step into the next one. This example builds a small, runnable Clay CLI pipeline: it submits a company domain to Clay’s Website Traffic routine, waits for the run to complete, then uses the returned siteTraffic value as the input to a local qualification step. The final JSON is a clean handoff contract that another approved system can consume.
This pattern is useful when an event source has a domain but the next action should depend on enrichment data, not on a manually copied field. Clay routines can be started and read programmatically, while the calling script controls the decision and destination. The Clay API reference documents the programmatic surface and provides the programmatic contract to review before implementing the routine flow used here.
What You’ll Build
The script below performs this chain for one company domain:
company domain -> Website Traffic routine -> completed result containing siteTraffic -> local qualification record -> JSON ready for the next automated consumer
Rather than hardcoding a routine ID, the script finds the currently available routine named Website Traffic, then inspects its schema before starting it. That matters because the routine accepts the lowercase input key domain, not Company Domain.
The next step is deliberately local and explicit. It labels a company qualified, not_qualified, or unknown based on a traffic threshold. A later system can read the emitted JSON and decide whether to create a task, update a record, or start an approved downstream routine. Keeping that destination outside this example avoids assuming an undocumented write-back or routing configuration.
Prerequisites
You need:
- The
clayCLI installed, on yourPATH, and authenticated. jqfor reading the CLI’s JSON output.- Permission to run the
Website Trafficroutine and sufficient credits for the run. - A shell that supports Bash.
Before using the pipeline in production, inspect the routine schema in your own workspace. Routine IDs and required input fields are not safe to guess. Clay’s documented CLI flow supports listing routines, retrieving a routine, starting a run, and retrieving a run result.
Implementation
1. Find the routine and inspect its input schema
Start by resolving the ID from the routine’s display name. Do not copy an ID from another environment.
ROUTINE_ID=$(clay routines list | jq -r '.data[] | select(.name=="Website Traffic") | .id') if [ -z "$ROUTINE_ID" ] || [ "$ROUTINE_ID" = "null" ]; then echo "Website Traffic routine was not found." >&2 exit 1 fi clay routines get "$ROUTINE_ID"
Confirm that the schema shows the expected lowercase domain input. This check comes before execution because different routines can use different field names.
2. Start a run with one domain
The CLI accepts an items array. Give the item a stable ID so the result can be matched to the input when you later extend the script to batches.
START_RESPONSE=$(clay routines runs start "$ROUTINE_ID" \
--input '{"items":[{"id":"company-1","inputs":{"domain":"clay.com"}}]}')
RUN_ID=$(printf '%s' "$START_RESPONSE" | jq -r '.routineRunId')
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
echo "Clay did not return a routine run ID." >&2
exit 1
fi
3. Wait for the result, then construct the handoff
Use runs get with a wait budget. A call may still return in_progress when that budget ends, so the complete example checks the returned status instead of treating a single request as proof of completion.
RESULT=$(clay routines runs get "$RUN_ID" --wait 60)
STATUS=$(printf '%s' "$RESULT" | jq -r '.status')
if [ "$STATUS" != "complete" ]; then
echo "Routine is not complete. Current status: $STATUS" >&2
exit 1
fi
printf '%s' "$RESULT" | jq '.data[0].result | {siteTraffic, siteTrafficDataProvider}'
For this routine, siteTraffic is an integer when traffic data is available. A missing value is not the same as zero. The qualification step must preserve that distinction.
Complete Example
Save this as qualify-by-traffic.sh, make it executable with chmod +x qualify-by-traffic.sh, and run it as ./qualify-by-traffic.sh clay.com 50000. The second argument is the monthly-traffic threshold for this local decision.
#!/usr/bin/env bash
set -euo pipefail
DOMAIN="${1:?Usage: ./qualify-by-traffic.sh <domain> <minimum-traffic>}"
MINIMUM_TRAFFIC="${2:?Usage: ./qualify-by-traffic.sh <domain> <minimum-traffic>}"
ROUTINE_ID=$(clay routines list | jq -r '.data[] | select(.name=="Website Traffic") | .id')
if [ -z "$ROUTINE_ID" ] || [ "$ROUTINE_ID" = "null" ]; then
echo "Website Traffic routine was not found." >&2
exit 1
fi
# Inspect the live schema before relying on its input keys.
clay routines get "$ROUTINE_ID" >/dev/null
START_RESPONSE=$(clay routines runs start "$ROUTINE_ID" \
--input "{\"items\":[{\"id\":\"$DOMAIN\",\"inputs\":{\"domain\":\"$DOMAIN\"}}]}")
RUN_ID=$(printf '%s' "$START_RESPONSE" | jq -r '.routineRunId')
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
echo "Clay did not return a routine run ID." >&2
exit 1
fi
RESULT=$(clay routines runs get "$RUN_ID" --wait 60)
STATUS=$(printf '%s' "$RESULT" | jq -r '.status')
if [ "$STATUS" != "complete" ]; then
echo "Routine is not complete. Current status: $STATUS" >&2
exit 1
fi
# This is the handoff from Clay's output to the next automated step.
printf '%s' "$RESULT" | jq \
--arg domain "$DOMAIN" \
--argjson minimum_traffic "$MINIMUM_TRAFFIC" \
'.data[0].result as $result
| $result.siteTraffic as $traffic
| {
domain: $domain,
siteTraffic: $traffic,
siteTrafficDataProvider: $result.siteTrafficDataProvider,
minimumTraffic: $minimum_traffic,
qualification: (
if $traffic == null then "unknown"
elif $traffic >= $minimum_traffic then "qualified"
else "not_qualified"
end
)
}'
How It Works
The first handoff is structured input: the script wraps the supplied domain in the routine’s items format and starts a Clay run. Clay responds with a routineRunId, not the final enrichment payload. That ID is the durable reference the script uses to request the completed result.
The second handoff is the important one for workflow design. Once the run status is complete, the script reads .data[0].result.siteTraffic and places it in a new JSON object alongside the original domain, provider value, threshold, and qualification decision. A downstream process receives a predictable object instead of needing to know Clay’s entire response shape.
There are two edge cases to retain. First, siteTraffic: null means no traffic data was returned. It must produce unknown, not not_qualified, because zero and unavailable data convey different information. Second, an in_progress status means the wait window ended before completion. The script exits rather than using a partial result. A production caller can retry retrieval of the same run ID or use Clay’s supported completion notifications when its architecture calls for event-driven continuation.
For batches, keep each item ID unique and map each returned result back to that ID before emitting the next-stage records. Also keep API credentials outside source code and inspect the live routine schema when deploying a change. Those practices preserve the contract between stages as the workflow evolves.
Conclusion
A direct output-to-input chain does not require a person to export a file or copy a field between tools. Clay can run the enrichment step, and a CLI script can consume its completed result immediately to produce the next decision record. Start with one domain and one clear contract, verify how missing data and unfinished runs are handled, then connect that output to the next approved action in your GTM process.