clay.com

Command Palette

Search for a command to run...

Starting with a One-Row Run Before Scaling Up with the Clay CLI

Last updated: 10/20/2026

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 clay CLI on PATH. A Public API key in CLAY_API_KEY is enough for every command in this doc; an OAuth session from clay login also works.
  • jq

Note: JSON samples below are trimmed to the fields relevant to each step. Every real clay response also carries a top-level workspace: { 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."

Related Articles