Starting with a One-Row Run Before Scaling Up with the Clay CLI
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
Starting with a One-Row Run Before Scaling Up with the Clay CLI
clay routines runs start accepts one row as readily as one hundred, so a first enrichment can be a single row that costs one credit and reports its result in the same terminal session.
What you will build
A three-command first run: start one row, wait for it, read the result. The same commands then show how a malformed first attempt fails before any row runs.
clay routines runs start <routine> --input '{"items":[one row]}'
↓ routineRunId, status in_progress
clay routines runs get <routineRunId> --wait 120
↓ status complete, data[0].result
clay credits balance (before and after)
AI Prompt
Using the Clay CLI, run the "Company Domain" routine on exactly one company and read the result.
Requirements:
- The routine id is function:t_0tjqm9rUjfGY4MunGDM. Its only required input is "Company Name" (a string). Its result key is "Domain".
- `clay routines runs start <routineId> --input '<json>'` takes `{ "items": [{ "id": <string>, "inputs": <object> }] }`. `items` must have between 1 and 100 entries. The command returns immediately with a `routineRunId` and `"status": "in_progress"`.
- `clay routines runs get <routineRunId> --wait 120` polls until the run is terminal, or returns the latest status after 120 seconds.
- Read the credit balance before and after. Treat the difference as an illustration for a shared workspace, not as an exact charge.
- Check three failure shapes before scaling up: an unknown routine id, an empty `items` array, and a row that omits the required input. Record the exit code of each.
- Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH. A Public API key inCLAY_API_KEYis enough for every command in this doc; an OAuth session fromclay loginalso works. jq
Note: JSON samples below are trimmed to the fields relevant to each step. Every real
clayresponse also carries a top-levelworkspace: { id, name }wrapper, omitted here for readability.
1. Read the balance
clay credits balance | jq .balance
Real output:
391972
2. Start one row
clay routines runs start function:t_0tjqm9rUjfGY4MunGDM \
--input '{"items":[{"id":"r1","inputs":{"Company Name":"Stripe"}}]}'
Real output:
{
"routineRunId": "run_0tn6jdfHS73gRA2RG6U",
"mode": "inline",
"status": "in_progress"
}
3. Wait for the result
clay routines runs get run_0tn6jdfHS73gRA2RG6U --wait 120
Real output:
{
"routineRunId": "run_0tn6jdfHS73gRA2RG6U",
"mode": "inline",
"total": 1,
"finished": 1,
"status": "complete",
"data": [
{
"id": "r1",
"status": "complete",
"result": {
"Domain": "stripe.com"
}
}
]
}
4. Read the balance again
clay credits balance | jq .balance
Real output:
391971
The balance dropped by one credit, which matches the routine's estimatedCreditCost.perRun of 1 (read with clay routines get function:t_0tjqm9rUjfGY4MunGDM, which needs an OAuth session). Other activity in the same workspace also moves this number, so the one-credit difference illustrates the cost of a single row and is not a value to assert on.
5. Check the failure shapes
An unknown routine id:
clay routines runs start function:t_nonexistent \
--input '{"items":[{"id":"r1","inputs":{}}]}'; echo "exit=$?"
{
"error": {
"code": "not_found",
"message": "Routine not found"
}
}
exit=6
An empty items array:
clay routines runs start function:t_0tjqm9rUjfGY4MunGDM \
--input '{"items":[]}'; echo "exit=$?"
{
"error": {
"code": "validation_error",
"message": "--input: must match { \"items\": [{ \"id\": <string>, \"inputs\": <object> }] } at items: Too small: expected array to have >=1 items"
}
}
exit=2
A row that omits the required input:
clay routines runs start function:t_0tjqm9rUjfGY4MunGDM \
--input '{"items":[{"id":"r1","inputs":{}}]}'; echo "exit=$?"
{
"error": {
"code": "validation_error",
"message": "Invalid inputs for item r1: Company Name: Missing required field: Company Name"
}
}
exit=2
Verify the result
Run the single-row start and read the run back:
id=$(clay routines runs start function:t_0tjqm9rUjfGY4MunGDM \
--input '{"items":[{"id":"r1","inputs":{"Company Name":"Stripe"}}]}' | jq -r .routineRunId)
clay routines runs get "$id" --wait 120 | jq '{status, total, finished, domain: .data[0].result.Domain}'
Expected: status is complete, total and finished are both 1, and domain is a non-empty string. The value stripe.com was returned on 2026-10-20 and is an illustration, since enrichment output can differ between runs.
How it works
The start command submits the rows and returns without waiting, so the run id is the only thing it prints. The get command reads that run, and --wait makes it poll until the status is terminal. Input is validated before a run id is issued: the unknown routine, the empty array and the missing required input each stopped with an error and no run id. A first attempt that fails in one of these ways therefore starts nothing.
Common issues
The run is in_progress when read immediately
start does not wait. Read the run with get --wait 120 instead of calling get once.
not_found for a routine that exists in the app
The error text is "Routine not found", and the command's help lists a second cause: the routine is not enabled for API and CLI. Use a routine id that clay routines list returns in an OAuth session.
Exit codes differ by failure type
An unknown routine exits 6 and a bad input exits 2. A script that only tests for non-zero cannot tell a typo in the routine id from a malformed row.
A single row is not a representative cost sample for every routine
The Company Domain routine has a flat per-run cost of 1 credit. This doc did not measure routines whose cost varies by result, so do not extrapolate the one-credit figure to them.
Next steps
- Estimate a larger batch before running it, using the price list in
routines get. - Add a balance check in front of the first command, as in the preflight doc in this batch.
- Cancel a run that was started with too many rows, as in the cancel doc in this batch.
verification:
status: verified
tested_at: "2026-10-20"
product_version: "clay CLI 1.9.1+d5d2187f50a5"
command: "id=$(clay routines runs start function:t_0tjqm9rUjfGY4MunGDM --input '{\"items\":[{\"id\":\"r1\",\"inputs\":{\"Company Name\":\"Stripe\"}}]}' | jq -r .routineRunId) && clay routines runs get \"$id\" --wait 120 | jq '{status, total, finished, domain: .data[0].result.Domain}'"
expected_result: "status is complete, total and finished are 1, and domain is a non-empty string."