# Get workspace credit balances
Source: https://developers.clay.com/api-reference/credits/get-workspace-credit-balances
/openapi.json get /credits/balance
Returns the current credit balances for the workspace associated with the API key. Reading balances does not consume credits.
# Get the authenticated user
Source: https://developers.clay.com/api-reference/me/get-the-authenticated-user
/openapi.json get /me
Returns the Clay user and workspace associated with the API key.
# Execute a routine against 1-100 items
Source: https://developers.clay.com/api-reference/routines/execute-a-routine-against-1-100-items
/openapi.json post /routines/{routine_id}/run
Starts an asynchronous routine run for up to 100 input items.
# Fetch progress and results for a batch run
Source: https://developers.clay.com/api-reference/routines/fetch-progress-and-results-for-a-batch-run
/openapi.json get /routines/run-batch/{routine_run_id}/results
Returns current status and results for an asynchronous batch routine run.
# Fetch progress and results for a routine run
Source: https://developers.clay.com/api-reference/routines/fetch-progress-and-results-for-a-routine-run
/openapi.json get /routines/run/{routine_run_id}/results
Returns current status and paginated results for an asynchronous routine run.
# Issue a presigned PUT URL for uploading a batch input JSONL
Source: https://developers.clay.com/api-reference/routines/issue-a-presigned-put-url-for-uploading-a-batch-input-jsonl
/openapi.json post /routines/{routine_id}/run-batch/upload-url
Creates a presigned URL for uploading a JSONL file used by a batch routine run.
# Start an async routine run-batch over an uploaded JSONL file
Source: https://developers.clay.com/api-reference/routines/start-an-async-routine-run-batch-over-an-uploaded-jsonl-file
/openapi.json post /routines/{routine_id}/run-batch/start
Starts an asynchronous batch routine run over a previously uploaded JSONL file.
# Create a search from a Clay search query
Source: https://developers.clay.com/api-reference/search/create-a-search-from-a-clay-search-query
/openapi.json post /search/query-mode
Starts a new Clay search from a Clay advanced search query. The source type is detected from the query and returned in the response. Count-mode and jobs queries are not supported.
# Create a search from structured filters
Source: https://developers.clay.com/api-reference/search/create-a-search-from-structured-filters
/openapi.json post /search/filters-mode
Deprecated: create searches from a Clay search query with POST /search/query-mode instead. Starts a new Clay search from a source type and structured filter fields. Existing filters-mode searches can still be paged with POST /search/filters-mode/{search_id}/run.
# Get the Clay search query reference
Source: https://developers.clay.com/api-reference/search/get-the-clay-search-query-reference
/openapi.json get /search/query-mode/reference
Returns the Clay search query reference document (markdown), covering the queryable fields and the query grammar. Use it to author a Clay advanced search query before creating a query-mode search.
# List the filter fields available for a search source type
Source: https://developers.clay.com/api-reference/search/list-the-filter-fields-available-for-a-search-source-type
/openapi.json get /search/filters-mode/fields
Deprecated: filters-mode search creation is being retired in favor of query-mode. Use GET /search/query-mode/reference to discover the query grammar instead. Returns every filter field accepted by POST /search/filters-mode for the given source type, including each field's type, description, allowed values, and usage guidance.
# Run the query-mode iterator and return the next page of results
Source: https://developers.clay.com/api-reference/search/run-the-query-mode-iterator-and-return-the-next-page-of-results
/openapi.json post /search/query-mode/{search_id}/run
Returns the next page of records for an existing query-mode search.
# Run the search iterator and return the next page of results
Source: https://developers.clay.com/api-reference/search/run-the-search-iterator-and-return-the-next-page-of-results
/openapi.json post /search/filters-mode/{search_id}/run
Deprecated: filters-mode search is being retired in favor of query-mode. This endpoint remains available to page searches created earlier in filters mode. Returns the next page of records for an existing filters-mode search.
# Run a structured query across one or more tables
Source: https://developers.clay.com/api-reference/tables/run-a-structured-query-across-one-or-more-tables
/openapi.json post /tables/query
Runs a structured query against Clay table data and returns records with field metadata. Results are paginated: pass the returned cursor back to fetch the next page. Scans return rows in least-recently-updated-first order and reflect writes that land while you paginate — a scan returns every record visible when it started and picks up records written while it runs, and a record updated mid-scan can be returned again with fresher data, so deduplicate by id if you need each record once.
# Get the runs search query reference (beta)
Source: https://developers.clay.com/api-reference/workflowsruns/get-the-runs-search-query-reference-beta
/openapi.json get /workflows/runs/query/reference
Returns the Clay workflow-run query reference document (markdown), covering the queryable run fields, node predicates, content search, and the query grammar. Use it to author a workflow-run query.
# Search runs by query (beta)
Source: https://developers.clay.com/api-reference/workflowsruns/search-runs-by-query-beta
/openapi.json post /workflows/runs/query
Execute a Clay workflow-run query. A `select` query returns matching runs newest-first with a `cursor` for the next page; a `count` query returns the number of matching runs. Get the query grammar with GET /workflows/runs/query/reference. Results are read from an eventually-consistent replica (replication lag is typically a few seconds), so a just-created or just-transitioned run may briefly be missing or show its prior status.
# Audiences
Source: https://developers.clay.com/audiences
Work with people, companies, deals, saved segments, activities, and signal events from the Clay CLI.
Audiences brings your workspace's people, companies, and deals into one data model. Use it to find the right records, understand their context, and act on what is happening across your go-to-market motion.
## Core concepts
| Concept | What it represents |
| - | - |
| Records | People, companies, and deals in your workspace |
| Fields | The properties available on each record type |
| Saved segments | Reusable filters that stay current as people and company records change |
| Activities | Interactions such as calls, emails, sequencer events, and imported CRM activity |
| Signal events | Events captured when Clay detects a relevant change, such as a job change, promotion, or news event |
## People, companies, and deals
People and companies are the primary record types in Audiences. Add them from a Clay search, or import them from your CRM or data warehouse. Deals are associated with people or companies, and you can search them too.
## Activities and signal events
Activities capture interactions that happened across connected systems. Signal events are captured events such as promotion and news about a company.
## Use the CLI
Run the built-in help for the current subcommands, inputs, JSON output, errors, and examples:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay audiences --help
```
Create and manage signal triggers that produce signal events.
Enrich people who are missing phone numbers with an agent and Workflow.
Use an agent to find patterns in recent successful deals.
# CLI basics
Source: https://developers.clay.com/concepts/cli-basics
Understand the Clay CLI output contract, exit codes, environment variables, and authentication.
The Clay CLI (`clay`) is JSON-first: every command writes machine-readable JSON to stdout on success and a structured error envelope to stderr on failure. There are no spinners, colors, or progress bars, so agents and scripts can branch on the output and exit code directly.
## Output contract
| Result | Behavior |
| - | - |
| Success | JSON is written to stdout, exit code `0`. |
| Failure | `{ "error": { "code", "message", "details"? } }` is written to stderr, non-zero exit code. |
Pipe stdout straight into `jq`, and read the exit code (`$?`) to decide what to do next.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay whoami | jq -r '.user.id'
```
## Exit codes
Branch on these from agents and scripts instead of parsing error text.
| Exit | Meaning |
| - | - |
| `0` | Success. |
| `1` | Generic or unrecoverable (`server_error`, `contract_mismatch`, `conflict`, `internal_error`, `invalid_config_file`). |
| `2` | `validation_error` — input was rejected as malformed. |
| `3` | `auth_required` \| `auth_invalid` \| `auth_forbidden` — run `clay login` to (re)authenticate. |
| `4` | `rate_limited` (HTTP 429) — `details` has `retryAfter` (seconds), plus `limit`/`remaining`/`reset` when Clay sends the `X-RateLimit-*` headers. |
| `5` | `network_error` \| `network_timeout` — could not reach Clay. |
| `6` | `not_found` (HTTP 404). |
## Environment variables
| Variable | Purpose |
| - | - |
| `CLAY_CONFIG_HOME` | Highest-precedence config directory parent; `config.json` and the identity cache live under `/clay`. |
| `XDG_CONFIG_HOME` | Used when `CLAY_CONFIG_HOME` is unset (`/clay`), falling back to `~/.config/clay` when neither is set. |
| `CLAY_REQUEST_TIMEOUT_MS` | Per-request network timeout in milliseconds (default `60000`). |
| `CLAY_UPLOAD_TIMEOUT_MS` | Bulk file-upload timeout in milliseconds (default `600000`). |
## Authentication
`clay login` opens a browser to authorize the CLI with OAuth — this works from a human terminal or an agent's shell tool. Use `clay whoami` as the canonical check that authentication is working, and `clay logout` to clear a stored credential.
Each sign-in covers one workspace — the one you pick on the consent screen. To work across several, run `clay login` once per workspace: signing into a second keeps the first. `clay workspaces list` shows what you are signed into, `clay workspaces current` shows which one commands run against, and `clay workspaces switch ` switches. Signing in makes the workspace just added the active one, so switch back explicitly if you were working in another. `clay logout` signs out of the active workspace and leaves the rest.
On machines where a local browser can't open — SSH sessions, containers, headless machines — use `clay login --device` instead. It prints a link and a short code; open the link in a browser on any device to approve the sign-in, and the CLI completes automatically. Run `clay login --help` for details.
# Execution model
Source: https://developers.clay.com/concepts/execution-model
Understand the primitives behind Clay routines, searches, tables, runs, and batch jobs.
Clay's stable developer surface is focused on execution and data access. It lets you run Clay logic and retrieve Clay data from outside the Clay UI.
Workflows are the Alpha building surface. Use them when you want to create, edit, validate, run, inspect, or batch-run Clay logic from the plugin or CLI.
## Core primitives
| Primitive | What it does |
| - | - |
| Routines | Run Clay functions and Workflows from the plugin, CLI, API, or MCP |
| Searches | Access Clay's proprietary database of companies and people |
| Tables | Query known Clay tables with structured filters and selected fields |
| Runs | Track asynchronous routine execution and poll for results |
| Batch jobs | Run the same routine across larger JSONL inputs |
## How teams use it
Most integrations start with a routine. A Clay function packages the workflow, input schema, provider choices, prompts, and output shape. Your system passes inputs to the routine and receives structured results.
Searches and tables are data access paths. Use searches to discover people and companies. Use tables when you already know the table and want structured query results.
Learn how to expose and run Clay functions.
# Overview
Source: https://developers.clay.com/index
Use Clay from agents, terminals, backend services, internal tools, and custom apps.
Clay used to live primarily in the Clay UI. Now Clay also works where your agents, developers, and business systems already are.
Use the developer platform to search Clay's GTM data, run reusable Clay logic, read table data, and work with Audiences programmatically.
## Start here
Best for Claude Code, Codex, Cursor, and agent-first work. The plugin ships skills and the Clay CLI.
Best for backend jobs, internal tools, custom apps, queues, and product workflows.
## Core primitives
| Primitive | Use it for |
| - | - |
| [Searches](/searches) | Find companies and people using Clay's GTM database |
| [Routines](/routines) | Run Clay-managed functions, custom functions, and Workflows |
| [Tables (Enterprise)](/tables) | Query existing Clay table data from known tables |
| [Audiences](/audiences) | Work with records, saved segments, activities, and signal events |
| [Signals](/signals) | Create triggers that detect relevant changes across records |
Start with the primitive that matches where your data lives and what you want to do.
## Choose the right primitive
* Need a target list? Use [Searches](/searches).
* Need enrichment, scoring, routing, or reusable logic? Use [Routines](/routines).
* Need existing table data? Use [Tables](/tables). Tables are Enterprise only.
* Need Audiences records, saved segments, activities, or signal events? Use [Audiences](/audiences).
* Need triggers that watch records and produce signal events? Use [Signals](/signals).
## Start with a recipe
Pull a target list from Clay data, then run Clay-managed functions on the results.
Let an agent call Clay logic as part of its normal work.
Create, edit, validate, run, and inspect a Workflow from the plugin or CLI.
Use an agent to find patterns in recent successful deals.
# Authentication
Source: https://developers.clay.com/public-api/authentication
Authenticate requests with a Clay API key.
Every request to the Clay Public API must include a Clay API key in the `clay-api-key` header. Store your key in an environment variable and pass it in the header:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
export CLAY_PUBLIC_API_KEY="your_api_key"
curl https://api.clay.com/public/v0/me \
-H "clay-api-key: $CLAY_PUBLIC_API_KEY"
```
API keys are tied to a Clay user and workspace access. Create one under [API and CLI → API keys](https://app.clay.com/workspaces/~/api-and-cli?tab=api-keys), with `clay api-keys create --name ""` in the CLI, or by asking your agent after installing the [agent plugin](/quickstart#agent-plugin). Keep keys server-side and do not expose them in browser code, mobile apps, public repositories, logs, or analytics tools.
## Header
| Header | Required | Description |
| - | - | - |
| `clay-api-key` | Yes | Personal API key for the Clay Public API. |
## Failed authentication
Requests without a valid API key return a non-2xx response with the standard error shape:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"message": "Authentication failed"
}
```
# Errors
Source: https://developers.clay.com/public-api/errors
Understand Clay Public API error responses.
Non-2xx responses return a JSON object with a human-readable `message`.
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"message": "Validation failed"
}
```
Use the HTTP status code as the machine-readable error category. Error response bodies do not currently include stable error codes.
## Recommended handling
* Treat `401` and `403` as authentication or authorization failures.
* Treat `404` as a missing resource or unavailable endpoint.
* Treat `409` and `422` as request state or validation problems.
* Treat `429` as rate limiting and retry after backing off.
* Treat `5xx` as transient server errors and retry with exponential backoff when the request is safe to retry.
For async endpoints, a `202` response means the job is still running. Poll the result endpoint until it returns a terminal `200` response. On a terminal `200`, treat unrecognized `status` values as an unhandled terminal outcome — do not assume the set of statuses is closed.
# Pagination
Source: https://developers.clay.com/public-api/pagination
Handle paginated collections and stateful result iterators.
The Clay Public API uses two response patterns for multi-item endpoints.
## Cursor pagination
Stable collection endpoints return `data` and, when another page is available, `cursor`.
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"data": [],
"cursor": "next_page_token"
}
```
Send the returned cursor on the next request. If `cursor` is omitted, there are no more pages.
## Stateful iterators
Some endpoints consume state as they return results. These responses return `data` and `has_more` instead of a cursor.
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"data": [],
"has_more": true
}
```
Call the endpoint again while `has_more` is `true`.
## Limits
Endpoints that accept `limit` default to a safe page size. Use smaller page sizes when you need lower latency and larger page sizes when you want fewer round trips.
# Rate limits
Source: https://developers.clay.com/public-api/rate-limits
Understand Clay Public API rate limits and how to handle 429 responses.
The Clay Public API enforces a per-workspace request rate limit. When you exceed it, Clay returns HTTP `429` and you should back off before retrying.
## Reading the limit
When a request is rate limited, Clay returns `429` with a `Retry-After` header (seconds to wait). When available, Clay also sends `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` so you can pace requests before you hit the ceiling.
The CLI surfaces the same signal: rate-limited commands exit with code `4`, and the error `details` include `retryAfter` (seconds), plus `limit`, `remaining`, and `reset` when Clay sends the `X-RateLimit-*` headers.
## Recommended handling
* Treat `429` as retryable. Wait for the `Retry-After` interval, then retry.
* Add exponential backoff and jitter when you issue many requests concurrently.
* Prefer batch and async endpoints over tight polling loops. For async runs, poll the result endpoint at a modest interval rather than as fast as possible.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# CLI: exit code 4 signals rate limiting; back off using details.retryAfter.
clay routines runs list >out.json 2>err.json
status=$?
if [ "$status" -eq 4 ]; then
sleep "$(jq -r '.error.details.retryAfter // 5' err.json)"
# ...then retry the command
fi
```
# Webhooks
Source: https://developers.clay.com/public-api/webhooks
Get notified when a routine run finishes, then verify and handle the delivery.
Webhooks let Clay notify your service when a routine run finishes, so you can react without polling. Register a webhook, pass its id when you start a run, and handle the signed `POST` Clay sends once results are ready.
## Register a webhook
Create a webhook with the CLI — run `clay webhooks --help` for the full command surface (create, list, test, delete):
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay webhooks create https://example.com/hooks/clay
```
`create` returns the signing secret exactly once — store it immediately, it can't be retrieved later:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"id": "wh_abc123",
"url": "https://example.com/hooks/clay",
"createdAt": "2026-06-16T17:50:00.000Z",
"signingSecret": "whsec_..."
}
```
## Trigger a delivery
Pass the webhook id as `webhook_id` when you start a routine run (see [Routines](/routines/api)). Clay sends a signed `POST` to the webhook URL when the run is ready to read.
## Delivery payload
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"webhookId": "wh_abc123",
"createdAt": "2026-06-16T17:50:00.000Z",
"data": {
"routine_run_id": "run_abc123"
}
}
```
For test events, `data` is `{}`. The `routine_run_id` can identify an inline or a bulk run. If one webhook handles both, store the run mode when you start the run, or use `clay routines runs get`, which fetches results for either mode.
## Verify and fetch results
Clay signs the exact request body with your webhook signing secret and sends it in the `X-Clay-Signature` header. Verify the signature before trusting a delivery, then fetch the run's results.
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import crypto from 'node:crypto';
import express from 'express';
const app = express();
function sign(body) {
return `sha256=${crypto
.createHmac('sha256', process.env.CLAY_WEBHOOK_SIGNING_SECRET)
.update(body, 'utf8')
.digest('hex')}`;
}
function signaturesMatch(actual, expected) {
const actualBuffer = Buffer.from(actual);
const expectedBuffer = Buffer.from(expected);
return actualBuffer.length === expectedBuffer.length && crypto.timingSafeEqual(actualBuffer, expectedBuffer);
}
async function fetchRunResults(routineRunId) {
// For batch routine runs, use `/public/v0/routines/run-batch/${routineRunId}/results`.
const result = await fetch(`https://api.clay.com/public/v0/routines/run/${routineRunId}/results`, {
headers: { 'clay-api-key': process.env.CLAY_PUBLIC_API_KEY },
});
return result.json();
}
app.post('/hooks/clay', express.raw({ type: 'application/json' }), async (req, res) => {
const body = req.body.toString('utf8');
const actualSignature = req.get('X-Clay-Signature') ?? '';
const expectedSignature = sign(body);
if (!signaturesMatch(actualSignature, expectedSignature)) {
return res.sendStatus(401);
}
const event = JSON.parse(body);
const routineRunId = event.data.routine_run_id;
const run = await fetchRunResults(routineRunId);
return res.sendStatus(204);
});
```
Webhook delivery is not guaranteed. Use webhooks to react faster, but keep polling the run's results as a fallback.
# Quickstart
Source: https://developers.clay.com/quickstart
Build with Clay from your coding agent, or call the Clay API from your own applications.
There are two ways to use Clay as a developer: install the agent plugin to build with Clay inside your coding agent, or call the Public API directly from your own applications and services.
## Agent plugin
The agent plugin gives your coding agent Clay's skills and the `clay` CLI — the fastest way to build with Clay from a coding agent.
It requires a coding-agent host with a shell — Claude Code, Codex, or Cursor — and doesn't work in general-purpose chat apps like Claude Desktop, claude.ai, or ChatGPT that can't run the CLI.
Copy this into your agent of choice and let it install and set up the plugin for you:
```
Set up the Clay plugin by following the steps in
https://github.com/clay-run/agent-plugins
```
This runs the plugin's `setup` skill, which puts `clay` on your PATH, signs you in, and verifies the CLI. Sign-in opens a browser to authorize the CLI.
Manual install and setup instructions for Claude Code, Codex, and Cursor.
## API
Use the Public API to call Clay from your own applications and services — backend jobs, internal tools, queues, and product features. Requests authenticate with a Clay API key in the `clay-api-key` header.
Endpoint paths, request bodies, response schemas, and an interactive try-it console.
### Get an API key
You can create an API key three ways:
* Ask your agent to generate one for you after installing the [agent plugin](#agent-plugin).
* Run `clay api-keys create --name ""` with the `clay` CLI. The key is returned once, in the `apiKey` field.
* Create one yourself in Clay under [API and CLI → API keys](https://app.clay.com/workspaces/~/api-and-cli?tab=api-keys).
Keep keys server-side. Do not expose them in browser code, mobile apps, public repositories, logs, or analytics tools. See [Authentication](/public-api/authentication) for details.
# Give an agent access to a Clay function
Source: https://developers.clay.com/recipes/agent-function-access
Let an agent call Clay-managed or custom functions from its normal workflow.
Use this pattern when you want Claude Code, Codex, or Cursor to call a Clay function for structured GTM data.
## 1. Install the Clay plugin
The Clay plugin gives agents Clay's skills and the `clay` CLI.
Install the plugin and sign in.
## 2. Choose a function
Use a Clay-managed function for common jobs like finding emails or enriching companies. Use a custom function when your team already has Clay logic it wants agents to call.
Compare Clay-managed functions, custom functions, and Workflows.
## 3. Expose the function
For custom functions:
1. Open [Functions](https://app.clay.com/functions).
2. Select the function.
3. Open **Details**.
4. Enable **API** so the plugin CLI can run it.
5. Enable **MCP** only if a separate MCP client (not the plugin) should call it.
Publishing alone does not enable MCP access. Both listing and running a function by id require it. See [function access settings](/routines/custom-functions#expose-a-function) and [MCP troubleshooting](/routines/custom-functions#access-a-published-function-through-mcp).
## 4. Let the agent call it
After setup, the agent discovers and runs the function through the plugin's routines skill. Keep the input schema tight and the output predictable.
Good functions for agents:
* Find a person's work email.
* Enrich a company by domain.
* Score an inbound lead.
* Summarize account research.
* Route a lead to the right owner or motion.
# Build a Workflow (Alpha)
Source: https://developers.clay.com/recipes/build-workflow-alpha
Use the Clay plugin and CLI to create, edit, run, and inspect a Workflow.
Use Workflows when you want to build and edit Clay logic from an agent or terminal instead of the Clay UI.
**Workflows are in Alpha.** They are earlier and more experimental than Clay-managed functions and custom functions.
## When to use this
* Agent-first creation and editing in Claude Code, Codex, or Cursor.
* CLI-based run, inspect, and debug loops.
* Code inside the flow.
* A flow created from a prompt, CSV, webhook, Audience, or existing Clay table.
* Runs that avoid the 50,000 row limit.
## 1. Install the plugin
Install the plugin and sign in.
## 2. Create or open a Workflow
List existing Workflows:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay workflows list
```
Create a new Workflow:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay workflows create --name "Enrich target accounts"
```
## 3. Build and edit with an agent
Ask your agent to build the Workflow. The Clay plugin lets the agent read the Workflow, edit nodes, validate the graph, and test Clay actions before wiring them in.
Example prompts:
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Build a Workflow that takes a company domain, enriches company data, finds relevant sales leaders, and returns structured output for my CRM.
```
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Turn this Clay table into a Workflow I can run in batches. Keep the same enrichment steps, but add a code step that filters out companies with fewer than 100 employees.
```
## 4. Run and inspect
Start a test run:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
echo '{"domain":"clay.com"}' | clay workflows runs test wf_abc123 --inputs -
```
Fetch run status:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay workflows runs get wf_abc123 wfr_abc123 --nodes
```
Inspect failed steps:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay workflows runs steps wf_abc123 wfr_abc123 --status failed
```
## 5. Use snapshots
Use snapshots to inspect changes or restore an earlier Workflow state.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay workflows snapshots list wf_abc123
```
Learn the Workflow model and how it compares to functions.
# Encode Clay functions into business systems
Source: https://developers.clay.com/recipes/business-systems
Call Clay functions from backend jobs, internal tools, queues, and product workflows.
Use this pattern when Clay should run behind a backend job, queue, webhook, internal tool, or custom UI.
## Recommended path
| Need | Use |
| - | - |
| Common enrichment or research | Clay-managed function |
| Existing team-specific Clay logic | Custom function |
| Logic you want to build and edit from an agent or CLI | Workflows (Alpha) |
## Call from the API
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
ROUTINE_RUN_ID=$(curl --request POST \
--url "https://api.clay.com/public/v0/routines/function:t_abc123/run" \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data '{
"items": [
{
"id": "row-1",
"inputs": {
"domain": "clay.com"
}
}
]
}' | jq -r '.routine_run_id')
curl --request GET \
--url "https://api.clay.com/public/v0/routines/run/$ROUTINE_RUN_ID/results" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY"
```
## Call from the plugin or CLI
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
echo '{"items":[{"id":"row-1","inputs":{"domain":"clay.com"}}]}' \
| clay routines runs start function:t_abc123 --input -
```
## Batch the same function
Learn how function and Workflow batch runs fit together.
# Run a search, then enrich with a function
Source: https://developers.clay.com/recipes/search-and-enrich
Use Searches to find records, then run Clay-managed functions on the results.
This is the simplest high-value Clay developer flow:
1. Use Searches to find companies or people.
2. Pass the results into a routine.
3. Use Clay-managed functions to enrich the records.
For example, you might search for heads of sales at B2B SaaS companies, then run a Clay-managed function to find work emails.
## 1. Run a search
Fetch the query reference, write a query, create a search, then fetch the first page of results.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request GET \
--url https://api.clay.com/public/v0/search/query-mode/reference \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY"
QUERY='select from people where experiences.any('\
'is_current = true and '\
'job_title is_similar_to ("VP Sales", "Head of Sales") and '\
'company.estimated_employee_count >= 500 and '\
'company.industry = "Software Development")'
SEARCH_ID=$(curl --request POST \
--url https://api.clay.com/public/v0/search/query-mode \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data "$(jq -n --arg query "$QUERY" '{query: $query}')" \
| jq -r '.search_id')
curl --request POST \
--url "https://api.clay.com/public/v0/search/query-mode/$SEARCH_ID/run" \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data '{ "limit": 10 }'
```
## 2. Choose a function
Use a Clay-managed function when Clay already provides the enrichment you need, such as finding emails, phone numbers, company data, technology data, funding, or job openings.
Learn when to use Clay-provided functions.
## 3. Run the function
Run the function routine on the records you want to enrich.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
echo '{"items":[{"id":"person-1","inputs":{"domain":"example.com","full_name":"Ada Lovelace"}}]}' \
| clay routines runs start function:t_abc123 --input -
```
Then fetch the result:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay routines runs get run_abc123
```
## Next steps
Learn the search flow in more detail.
Run the same routine across many records.
# Routines API
Source: https://developers.clay.com/routines/api
Run Clay-managed functions and custom functions through the Public API.
Routines are the programmable way to run Clay logic. Through the Public API, you can run Clay-managed functions and custom functions from backend services, queue workers, internal tools, and custom apps.
Use [Clay-managed functions](/routines/clay-managed-functions) for common enrichment and research jobs. Use [custom functions](/routines/custom-functions) for team-specific Clay logic built in the Clay UI.
## Run a function routine
Custom function routine ids use the format `function:t_...`. To start a run, call `POST /routines/{routine_id}/run`.
Replace `function:t_abc123` and the input names with your function's routine id and inputs. Give each item an id you can use to match its result later.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
ROUTINE_RUN_ID=$(curl --request POST \
--url "https://api.clay.com/public/v0/routines/function:t_abc123/run" \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data '{
"items": [
{
"id": "row-1",
"inputs": {
"domain": "clay.com"
}
},
{
"id": "row-2",
"inputs": {
"domain": "example.com"
}
}
]
}' | jq -r '.routine_run_id')
```
## Read the results
Use the returned `routine_run_id` to request the run's results:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request GET \
--url "https://api.clay.com/public/v0/routines/run/$ROUTINE_RUN_ID/results" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY"
```
While the run is processing, the endpoint returns **HTTP 202** with progress counters. There is no `data` array yet:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"routine_run_id": "run_xyz789",
"status": "in_progress",
"total": 2,
"finished": 1
}
```
Repeat the GET request until it returns **HTTP 200** with `status: "complete"`. Use a delay between polls and a timeout appropriate for your application. For HTTP errors, follow the [error handling](/public-api/errors) and [rate limit](/public-api/rate-limits) guidance rather than continuing to poll unchanged.
Read individual results from **`data`**. Each item's `id` matches an id you supplied in the run request. Check each item's `status`: a completed run can contain failed items. For example, a function with a `company_name` output could return:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"routine_run_id": "run_xyz789",
"status": "complete",
"total": 2,
"finished": 2,
"data": [
{
"id": "row-1",
"status": "complete",
"result": {
"company_name": "Clay"
}
},
{
"id": "row-2",
"status": "failed",
"error": {
"message": "Provider request failed"
}
}
]
}
```
The keys inside `result` depend on your function's outputs. Use item ids to associate results with inputs rather than relying on response order. `finished` counts finished items, including failures; it is not a count of successful results.
### Retrieve every page
A completed run's results can span multiple pages. If the response includes `cursor`, pass that value to the same endpoint to retrieve the next page:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
NEXT_CURSOR=""
curl --get \
--url "https://api.clay.com/public/v0/routines/run/$ROUTINE_RUN_ID/results" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data-urlencode "cursor=$NEXT_CURSOR" \
--data-urlencode "limit=20"
```
Collect `data` from each page and continue with each returned cursor until `cursor` is omitted. Treat cursors as opaque values. `total` and `finished` describe the whole run, not the current page. See [pagination](/public-api/pagination) for the general cursor pattern.
This polling flow applies to runs started with `/routines/{routine_id}/run`. Runs started through the batch API use the separate [batch results endpoint](/routines/batch-runs).
## Webhook notifications
The `run` and `run-batch/start` requests accept an optional `webhook_id`. Clay notifies that webhook when the run finishes, so your system can react without polling.
Run `clay webhooks --help` for webhook creation, testing, delivery payloads, and signature verification.
## Batch run a function routine
For large input sets, create an upload URL, upload JSONL input, then start a batch run.
Learn how batch runs fit into Routines.
## When to use Workflows
Workflows are also routines, but they are in Alpha and are built differently. Use Workflows when you want to build, edit, validate, run, inspect, or batch-run Clay logic from the plugin or CLI instead of building the logic in the Clay UI.
Compare Workflows with functions.
# Batch runs
Source: https://developers.clay.com/routines/batch-runs
Run routines across many records.
Batch runs let you apply the same routine to many records.
Both functions and Workflows can be run programmatically in batches. The difference is how the routine is built:
* Functions are built and managed in the Clay UI, then run or batch-run programmatically.
* Workflows are in Alpha and can be built, edited, run, inspected, and batch-run from the plugin or CLI.
## Function batch runs
Use function batch runs when you have a Clay-managed function or custom function and want to apply it to a list of inputs.
CLI function batch runs use JSONL input:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay routines runs start function:t_abc123 --bulk rows.jsonl
```
Each JSONL line is one item:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "id": "row-1", "inputs": { "domain": "clay.com" } }
```
The CLI wraps the same Public API flow:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST "https://api.clay.com/public/v0/routines/function:t_abc123/run-batch/upload-url" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY"
```
Upload the JSONL file to the returned `upload_url`:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request PUT "$UPLOAD_URL" \
--header "Content-Type: application/x-ndjson" \
--data-binary @rows.jsonl
```
Start the batch run with the returned `file_id`:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST "https://api.clay.com/public/v0/routines/function:t_abc123/run-batch/start" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--header "Content-Type: application/json" \
--data '{ "file_id": "file_abc123" }'
```
Then fetch progress and the result URL:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request GET "https://api.clay.com/public/v0/routines/run-batch/run_xyz789/results" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY"
```
## Workflow batch runs
Use Workflow batch runs when you want the Workflow itself to be built and managed from the plugin or CLI.
Workflows are in Alpha. They are useful when you need agent-first building, run inspection, snapshots, code inside the flow, or runs that avoid the 50,000 row limit.
Learn when to use Workflows.
# Clay-managed functions
Source: https://developers.clay.com/routines/clay-managed-functions
Use Clay-provided functions for common enrichment and research jobs.
Clay-managed functions are Clay-provided routines for standard GTM data jobs.
Use Clay-managed functions when you need standard enrichment or research, such as:
| Category | Examples |
| - | - |
| Contact data | Work email, phone number, job title |
| Company identity | Domain, address, industry |
| Company size and revenue | Employee count, revenue |
| Technology and hiring | Tech stack, technology verification, job openings |
| Company intelligence | News, latest funding |
Common pattern: search for the right people at target accounts, then run a Clay-managed function to find work emails.
## When to use them
Use Clay-managed functions when Clay already provides the enrichment or research job you need, or when you want an agent, backend service, or batch job to call that enrichment without building a custom function first.
## Run from agents or systems
Call Clay-managed functions from the Clay plugin, CLI, MCP, or API.
Let an agent call a Clay-managed or custom function.
Combine Searches with Clay-managed functions.
# Custom functions
Source: https://developers.clay.com/routines/custom-functions
Run your own reusable Clay logic from agents, the CLI, MCP, or the API.
Custom functions are Clay functions your team builds in the Clay UI, then runs from agents, the CLI, MCP, or the API.
## What custom functions are good for
* Team-specific enrichment waterfalls.
* Account scoring and qualification.
* Inbound routing and territory logic.
* CRM hygiene and validation.
* Repeatable research workflows.
* Internal tools that need the same Clay logic your GTM team already trusts.
## Runs and batch runs
The key distinction is where the function is built:
* Build and manage the function in the Clay UI.
* Run and batch-run it programmatically from agents, the CLI, MCP, or API.
Call custom functions from backend services, queues, and internal tools.
## Expose a function
To call a custom function:
1. Open [Functions](https://app.clay.com/functions).
2. Create or select a function.
3. Open **Details**.
4. Enable the integrations you need, such as **API** or **MCP**.
5. Copy the `t_...` function id.
6. Prefix it with `function:` when you call it from the plugin, CLI, MCP, or API.
Custom function routine ids use the format `function:t_...`.
Each access setting enables a separate way to call the function:
| How you call the function | Access to enable |
| - | - |
| Public API, `clay` CLI, or an agent using the CLI | API access |
| Clay's MCP connector | MCP access |
| As a routine in a Claygent | Claygent access |
An agent can use either the CLI or MCP, so choose access based on its connection. Enabling one does not enable the others. Workspace and role permissions still apply.
## Access a published function through MCP
Publishing a function does not automatically enable MCP access. Enable MCP access in the function's settings before calling it through an MCP client. API access alone is not sufficient.
Call `list_subroutines` to find functions available to the connected MCP client. Use the returned `id` as `subroutine_id` when running a function through MCP.
### A published function is missing or cannot run by id
MCP access is required both to list a function and to run it by id. Supplying a known id does not bypass that requirement.
If a function is missing from `list_subroutines` or a run returns a not-found error:
1. Confirm the MCP client is connected to the workspace that contains the function.
2. Check that MCP access is enabled in the function's settings.
3. If access cannot be changed, ask a workspace admin to check the integration and role access settings.
4. Call `list_subroutines` again and use an id returned by that call.
A not-found error does not distinguish a nonexistent function from one unavailable to the connected client.
# Functions vs. Workflows
Source: https://developers.clay.com/routines/functions-vs-workflows
Choose between custom functions and Workflows for reusable Clay logic.
Functions and Workflows both live under Routines. Both can run Clay logic programmatically and support batch execution. Choose based on where you want to build the logic.
| Use case | Choose |
| - | - |
| You want Clay-provided enrichment or research | [Clay-managed functions](/routines/clay-managed-functions) |
| You already built reusable logic in the Clay UI | [Custom functions](/routines/custom-functions) |
| You want to create or edit the logic from an agent or terminal | [Workflows (Alpha)](/routines/workflows-alpha) |
| You want an agent to inspect and debug the run step-by-step | [Workflows (Alpha)](/routines/workflows-alpha) |
| You want to avoid the 50,000 row limit | [Workflows (Alpha)](/routines/workflows-alpha) |
## Use functions when
Use functions for:
* Existing Clay enrichment waterfalls.
* Common jobs handled by Clay-managed functions.
* Team-specific functions that are already trusted.
* Backend jobs and agents that just need to call the logic.
* Batch execution where the function already does what you need.
## Use Workflows when
Use Workflows when you want to build and edit outside the Clay UI.
Workflows are in Alpha. Use them for:
* Agent-built flows in Claude Code, Codex, or Cursor.
* CLI-first iteration, validation, testing, and debugging.
* Multi-step flows that benefit from run inspection and snapshots.
* Flows that need code inside the process.
* Large runs where you want to avoid the 50,000 row limit.
**Workflows are in Alpha.** For common enrichment and existing reusable logic, start with Clay-managed functions or
custom functions.
# Routines overview
Source: https://developers.clay.com/routines/index
Understand the routine types: Clay-managed functions, custom functions, and Workflows.
Routines are the umbrella for programmable Clay logic: enrichment, research, scoring, routing, cleanup, and other repeatable GTM work.
| Routine type | Use it when | Status |
| - | - | - |
| [Clay-managed functions](/routines/clay-managed-functions) | You want Clay-provided enrichment or research for common jobs | Available |
| [Custom functions](/routines/custom-functions) | You already have Clay logic you want to call from agents, the CLI, MCP, or the API | Available |
| [Workflows (Alpha)](/routines/workflows-alpha) | You want to create, edit, run, inspect, or batch-run Clay logic from the plugin or CLI | Alpha |
**Workflows are in Alpha.** They overlap with functions in what they can execute, but differ in how you build and
manage them.
## How routines are called
Routines can be called from the Clay plugin, CLI, MCP, or direct API integrations.
| Surface | What it is good for |
| - | - |
| Clay plugin | Agent workflows in Claude Code, Codex, and Cursor |
| CLI | JSON-first runs, batch runs, workflow testing, and debugging |
| MCP | Agent access to Clay objects and routines |
| API | Backend services, internal tools, queue workers, custom UIs, and product workflows |
## First pattern
1. Use [Searches](/searches) to find a list of companies or people.
2. Use a Clay-managed function to enrich the results.
3. Send the structured output to your CRM, warehouse, app, or agent.
See the basic search-plus-function flow.
# Workflows (Alpha)
Source: https://developers.clay.com/routines/workflows-alpha
Build, edit, run, inspect, and batch-run Clay Workflows from the plugin and CLI.
Workflows are an Alpha routine type for building Clay logic from the plugin and CLI.
**Workflows are in Alpha.** They are earlier than Clay-managed functions and custom functions. Expect the surface to
evolve.
## How Workflows differ from functions
Functions and Workflows can both run Clay logic programmatically. The difference is where you build the logic.
| Routine type | Build and manage | Run programmatically | Batch-run programmatically |
| - | - | - | - |
| Custom functions | Clay UI | Yes | Yes |
| Workflows | Plugin or CLI | Yes | Yes |
## Why use Workflows
* Build and edit directly from Claude Code, Codex, Cursor, or the CLI.
* Avoid the 50,000 row limit.
* Write code inside the flow.
* Start from prompts, CSVs, webhooks, Audiences, or existing Clay tables.
* Validate, run, inspect, debug, and restore snapshots programmatically.
## What a Workflow contains
Workflows start from a trigger, then run connected nodes.
| Node type | Use it for |
| - | - |
| Agent nodes | Reasoning, drafting, summarizing, classifying, and choosing next steps |
| Enrich nodes | Running a Clay action such as finding an email or enriching a company |
| Code nodes | Deterministic transformations, filtering, formatting, and custom logic |
Triggers can come from a CSV, webhook, Audience, Clay table, manual test run, or another configured source.
## What agents can do
With the Clay plugin, agents can read and edit Workflows, validate the graph, run test actions, start runs, inspect failed steps, pause or resume runs, and restore snapshots.
Walk through the agent-first Workflow path.
# Searches
Source: https://developers.clay.com/searches
Find companies and people in Clay's proprietary GTM database.
Searches let you find companies and people in Clay's GTM database, then fetch structured records to use in your application, workflow, or agent.
## How you search
Advanced search supports criteria in Clay's field catalog as well as cross-entity filters, such as people at companies matching firmographics, and nested Boolean logic. You fetch the query reference, write a query, create a search, and page through results.
Write Clay search queries with cross-entity criteria and nested Boolean logic.
## What you can search
| Source type | Use it for |
| - | - |
| `people` | Contacts, titles, locations, and profile data |
| `companies` | Accounts, domains, industries, and firmographics |
## Result limits
Clay caps how many search results a workspace can return through the API. These limits apply to results returned across the CLI and Public API, and they scale with your plan.
| Plan | Results per request | Results per search | Results per period | Reset date |
| - | - | - | - | - |
| Free | 50 | 50 | 100 per 30 days | Rolling (ages out daily at midnight UTC) |
| Trial | 50 | 50 | 10,000 for trial duration | Not applicable |
| Paid | 500 | Up to your period limit | 1,000,000 per 30 days | Rolling (ages out daily at midnight UTC) |
| Legacy paid (Starter, Explorer, Pro) | 500 | Up to your period limit | 1,000,000 per year | January 1 (UTC) |
| Enterprise | 500 | Up to your period limit | 10,000,000 per 30 days | Rolling (ages out daily at midnight UTC) |
* **Per request** is the largest limit you can request in a single call.
* **Per search** is the total results you can fetch across all pages of one `search_id`.
* **Reset date** is when the period limit resets. For rolling windows, usage ages out of the window daily at midnight UTC rather than resetting on a fixed calendar date.
Legacy Starter, Explorer, and Pro plans keep the yearly period limit. Legacy Enterprise plans use the Enterprise row. Moving to a current paid plan or Enterprise is what switches a workspace to the rolling 30-day limit.
When you exceed a limit, Clay returns HTTP `402` with a message naming the limit you hit. Period-limit errors also state when the limit resets. Malformed filters or other invalid input still return HTTP `400`. To increase a limit, paid customers can contact Clay Support; Enterprise customers should contact their assigned Clay GTME.
## Related guides
Set up your API key.
See the create-search schema and try-it UI.
Combine Searches with Clay-managed functions.
# Search with advanced queries
Source: https://developers.clay.com/searches/advanced
Find Clay companies or people with Clay's advanced search query language.
Advanced search supports criteria from Clay's field catalog as well as cross-entity filters and nested Boolean logic.
Advanced queries return either people or companies. Count queries and job searches are not available through the Public API.
## Get the query reference
Fetch the query reference before writing a query. It describes the available fields and grammar.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request GET \
--url https://api.clay.com/public/v0/search/query-mode/reference \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY"
```
## Create and run a people search
This pattern returns current software engineers whose employer is in the Software Development industry.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
QUERY='select from people where experiences.any('\
'is_current = true and '\
'job_title is_similar_to ("software engineer") and '\
'company.industry = "Software Development")'
SEARCH_ID=$(curl --request POST \
--url https://api.clay.com/public/v0/search/query-mode \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data "$(jq -n --arg query "$QUERY" '{query: $query}')" \
| jq -r '.search_id')
curl --request POST \
--url "https://api.clay.com/public/v0/search/query-mode/$SEARCH_ID/run" \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data '{"limit": 20}'
```
## Use cross-entity query patterns
Choose the record type you want returned, then query through its relationships.
### Find people based on their employer
Use `experiences.any(...)` to return people whose current employer meets your criteria.
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
select from people
where experiences.any(
is_current = true and
job_title is_similar_to ("engineer") and
company.technographics.any(vendor = "Salesforce")
)
```
### Find companies based on their employees
Use `people.exists(...)` to return companies that employ people matching your criteria.
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
select from companies
where people.exists(
is_current = true and
job_title is_similar_to ("VP Sales")
)
```
### Combine criteria with Boolean logic
Group related criteria with parentheses to express alternatives while keeping the company requirement.
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
select from people
where experiences.any(
is_current = true and
(
job_title is_similar_to ("VP Sales") or
job_title is_similar_to ("Head of Sales")
) and
company.estimated_employee_count >= 500
)
```
## Fetch more results
The run endpoint is a stateful iterator. Its response contains `data`, `has_more`, and `source_type`, and can include `exhaustion_reason`. If `has_more` is `true`, call `POST /search/query-mode/{search_id}/run` again to fetch the next page.
People results include a structured location and an array of experiences that matched the query. `matched_experiences` is always an array; it is empty when no specific experience matched.
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"data": [
{
"clay_profile_id": 42,
"name": "Jane Doe",
"first_name": "Jane",
"last_name": "Doe",
"location": {
"name": "New York, New York, United States",
"city": "New York",
"state_or_province": "New York"
},
"matched_experiences": [
{
"company": "Example Corp",
"title": "Software Engineer",
"location": "New York, New York, United States",
"start_date": "2024-01-01",
"end_date": null
}
]
}
],
"has_more": true,
"source_type": "people"
}
```
Company results have their own shape, including `clay_company_id`, `name`, `size`, `type`, `domain`, `country`, `industry`, `location`, `description`, `linkedin_url`, `annual_revenue`, and `total_funding_amount_range_usd`.
# Signals
Source: https://developers.clay.com/signals
Create and manage signal triggers that detect relevant changes across your people and companies.
Signal triggers watch records and produce signal events when Clay detects a relevant change. A trigger can watch a table view, one or more Audiences segments, or every record of its entity type.
## Available signal types
| Signal type | What triggers it | Setup |
| - | - | - |
| Job change | A tracked person changes companies | Web, CLI |
| Job posting | A tracked company posts a job that matches your criteria | Web, CLI |
| New hire | A tracked company hires someone who matches your criteria | Web, CLI |
| Promotion | A tracked person's title advances at their company | Web, CLI |
| News and fundraising | A tracked company appears in relevant news or announces funding | Web, CLI |
| Person topic intent | A tracked person researches a topic you configured | Web, CLI |
| Company topic intent | A tracked company researches a topic you configured | Web, CLI |
| Custom | A custom enrichment you configured detects a change | Web |
| Web intent | An identified company or person visits your website | Web |
Custom and Web intent signal triggers are configured in the Clay web app. Their signal events are still available through Audiences.
## Use the CLI
Use `clay signals` to create and manage CLI-supported signal triggers. Run the built-in help for the current commands, inputs, JSON output, errors, and examples:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay signals --help
```
Work with records, activities, and the signal events produced by these triggers.
# Tables (Enterprise)
Source: https://developers.clay.com/tables
Query known Clay tables with structured filters, selected fields, ordering, and pagination.
Tables let Enterprise customers read structured data from known Clay tables. Use table queries when your integration already knows which table it needs and wants specific fields, filters, ordering, and pagination.
Tables are available on Enterprise plans.
Clay tables can act as a GTM database for your downstream systems. You can build dashboards, internal tools, QA views, scoring jobs, and interactive apps on top of data that already exists in Clay.
The current public API does not include a list-tables endpoint. You need the table identifiers your integration uses before querying table data. You can find the table id in a Clay URL after `/tables/`, for example `https://app.clay.com/workspaces/{workspaceId}/tables/t_0te9i4tZEHwc9hihBXu`.
## Common uses
* Pull records into a dashboard or internal tool.
* Power interactive apps that search, filter, and inspect Clay table data.
* Run QA checks against known Clay tables.
* Sync selected table fields into another system.
* Power alerts, scoring models, and warehouse jobs.
## Query shape
Table queries are structured. You select fields, apply filters, and page through results with a cursor.
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
--url https://api.clay.com/public/v0/tables/query \
--header "Content-Type: application/json" \
--header "clay-api-key: $CLAY_PUBLIC_API_KEY" \
--data '{
"query": {
"tables": [
{
"id": "t_0te9i4tZEHwc9hihBXu"
}
],
"select": [
{
"field": "Company Name",
"as": "company_name"
},
{
"field": "Domain",
"as": "domain"
}
],
"filter": {
"field": "Domain",
"op": "is_not_empty"
},
"field_mode": "names"
},
"limit": 20
}'
```
`query` is required and holds the fields, filters, ordering, and joins. `limit` and `cursor` are top-level siblings of `query`: `limit` (max 100) caps the page size, and `cursor` pages through results.
The response includes a `data` array and an optional `cursor` for pagination. When a `cursor` is returned, pass it back as the top-level `cursor` in your next request to fetch the following page. Cell values are returned with a status so your integration can distinguish successful, empty, pending, and errored cells.
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"data": [
{
"company_name": {
"status": "success",
"value": "Clay",
"fields": null
},
"domain": {
"status": "success",
"value": "clay.com",
"fields": null
}
}
],
"fields": {
"company_name": {
"id": "field_company_name",
"name": "Company Name",
"type": "text"
},
"domain": {
"id": "field_domain",
"name": "Domain",
"type": "text"
}
},
"cursor": "eyJwYWdlIjoyfQ"
}
```
See the table-query schema and try-it UI.
# Agent workflows
Source: https://developers.clay.com/use-cases/agent-workflows
Use Clay with coding agents, MCP clients, local scripts, and JSON-first automations.
Clay is useful for agents because it gives them a structured way to run GTM work. Instead of asking an agent to scrape, guess, or call many providers directly, expose Clay functions as routines and return predictable JSON.
## Good agent tasks
* Run a Clay function on a company domain and summarize the structured output.
* Enrich a list of accounts from a JSON file.
* Search for companies or people, then pass results into another workflow.
* Trigger repeatable research or scoring logic from a local terminal.
* Use MCP to call Clay functions from a coding agent like Claude Code, Codex, or Cursor.
## Start with the CLI
The CLI is the fastest path for most agent workflows because it handles authentication locally and returns JSON that agents can inspect.
Authenticate, list routines, and run your first Clay routine.
# Analyze recent closed-won deals
Source: https://developers.clay.com/use-cases/analyze-recent-closed-won-deals
Use an agent and the Clay CLI to find patterns in recent successful deals.
Use the Clay plugin when you want an agent to inspect your Audiences deal data and support its analysis with the matching records.
Audiences must be enabled for your workspace.
Install the plugin and sign in.
## Ask your agent
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Check our closed-won deals since last week and look for patterns in what's working.
```
The agent can resolve available deal fields such as stage, close date, amount, and owner; fetch the deal records; and compare the recent closed-won set for recurring traits in those fields.
Deal searches cannot apply a saved segment or filter directly, so the agent pages through deal IDs, fetches their fields, and narrows the results locally:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay audiences fields list --entity-type deals
clay audiences records search-ids --entity-type deals
clay audiences records get --entity-type deals --ids 123,456
```
Ask the agent to report the exact date range it used and support each pattern with the matching deals.
## Next steps
Learn how records, fields, segments, activities, and signals fit together.
Enrich records before you score, route, sync, or act on them.
# Use Clay tables as a database
Source: https://developers.clay.com/use-cases/build-on-tables
Build dashboards, internal tools, and interactive apps on top of data that exists in Clay tables.
Clay tables can be more than a workspace view. For developer workflows, they can act as a GTM database that your services, dashboards, and apps query directly.
Use table queries when you already know which Clay table contains the data you need and you want to search, filter, select fields, order records, or page through results.
## What you can build
* Dashboards for pipeline health, enrichment coverage, routing QA, and account scoring.
* Internal tools that inspect, filter, or review Clay-enriched records.
* Interactive apps that let users search and browse GTM data stored in Clay tables.
* Sync jobs that push selected Clay fields into a CRM, warehouse, or product database.
* Monitoring jobs that alert when records match a specific GTM condition.
## Why build on tables
Clay tables often become the place where GTM data is cleaned, enriched, scored, and reviewed. Querying those tables lets you reuse that work instead of rebuilding a separate database or duplicating Clay logic in another system.
## How it works
The Tables endpoint accepts a structured query against a known table. You choose fields, filters, ordering, and pagination settings, then Clay returns records with field metadata.
The current public API does not include a list-tables endpoint. Your integration needs to know which table it should query.
Learn how table queries work.
Test a structured table query in the generated API reference.
# Enrich leads and accounts
Source: https://developers.clay.com/use-cases/enrich-leads-and-accounts
Use Clay to enrich records with contact, company, technology, hiring, funding, and firmographic data.
Use Clay when your system needs better GTM data before it can score, route, sync, or act on a lead or account. Clay can run enrichment waterfalls and return structured outputs to your app, CRM, data warehouse, or workflow engine.
## Common enrichments
| Category | Examples |
| - | - |
| Contact data | Work Email, Phone Number, Person Job Title |
| Company identity | Company Domain, Company Address, Company Industry |
| Company size and revenue | Employee Count, Company Revenue (Exact) |
| Technology and hiring | Verify Technology Usage, Website Techstack, Company Job Openings |
| Company intelligence | Company News, Company Latest Funding |
## Example workflows
* Enrich every signup with company domain, employee count, industry, revenue, tech stack, and latest funding.
* Find people at a target account, fetch work emails, and route them to the right outbound motion.
* Verify whether an account uses a target technology before assigning it to a campaign.
* Add recent company news and job openings to account scoring logic.
## Enrich Audiences records with a workflow
Audiences and Workflows must be enabled for your workspace.
Install the plugin and sign in before asking an agent to build the Workflow.
Ask your agent:
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Find me all the people without a phone number, create a workflow to enrich them, and write each phone number back to the same Audiences record.
```
The agent can inspect the available people fields, find records where the phone field is empty, and create a Workflow that enriches the matching people and writes the result back to Audiences.
Save this filter for the default Phone field as `missing-phone.json`:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"type": "GroupOp",
"combinationMode": "And",
"items": [
{
"type": "BinOp",
"key": "phone",
"dataPath": ["contact_entity_field_values", "field", "phone"],
"operator": "Empty",
"value": null,
"entityType": "CONTACT"
}
]
}
```
To target a different phone field, replace `phone` in both `key` and `dataPath` with the field ID returned by `clay audiences fields list`.
The underlying CLI flow creates a saved segment from the filter, then creates a Workflow and attaches the segment as its trigger:
```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
clay audiences fields list --entity-type people
AUDIENCE_ID=$(clay audiences create \
--entity-type people \
--name "People missing phone numbers" \
--filter ./missing-phone.json \
| jq -r '.id')
WORKFLOW_ID=$(clay workflows create \
--name "Enrich missing phone numbers" \
| jq -r '.id')
TRIGGER_ID=$(jq -n --arg segmentId "$AUDIENCE_ID" \
'{triggerType: "audience_segment", segmentId: $segmentId, entityType: "CONTACT"}' \
| clay workflows triggers create "$WORKFLOW_ID" --input - \
| jq -r '.resourceId')
TRIGGER_NODE_ID=$(clay workflows triggers get "$TRIGGER_ID" \
| jq -r '.workflowNodeId')
```
Creating the trigger also creates its canvas trigger node. The agent should choose a phone enrichment action from the workspace catalog, connect it after `$TRIGGER_NODE_ID`, and add a final **Upsert Audiences Record** tool node (`upsert-audiences-record`).
The final node should map the trigger's `$.fields.id` to `audiences_record_id`, map the enrichment result to `enriched_phone`, and use this `inputMappingConfig`:
```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
"entityType": { "type": "static", "value": "CONTACT" },
"lookupFields|selectedLookupFields": {
"type": "static",
"value": ["id"]
},
"lookupFields|id": {
"type": "reference",
"expression": "{{audiences_record_id}}"
},
"recordFields|selectedRecordFields": {
"type": "static",
"value": ["phone"]
},
"recordFields|phone": {
"type": "reference",
"expression": "{{enriched_phone}}"
},
"recordFields|removeNullValues": { "type": "static", "value": true }
}
```
Using the record ID makes the upsert update the person that triggered the run. Once the phone is written, that person no longer matches the missing-phone segment. Validate and test the Workflow before publishing it.
## Build it with Clay
Start with a Clay-managed function when the use case is standard. Use a custom function when your team has specific providers, fallback order, prompts, or output schemas.
Run Clay-managed functions or expose your own Clay functions through Routines.
# Use cases
Source: https://developers.clay.com/use-cases/index
See the GTM workflows you can run with Clay from a CLI, API, service, or agent.
Clay makes GTM intelligence executable. Use it when your product, agent, or operations system needs to call the same enrichment, research, scoring, and routing workflows your team trusts in Clay.
## What Clay helps you do
* Turn messy account, person, company, and hiring signals into structured outputs.
* Run waterfall-style enrichment without hard-coding providers into your app.
* Embed lead scoring, routing, research, and CRM hygiene logic into backend workflows.
* Give AI agents a predictable way to run GTM actions and receive JSON.
Add emails, phone numbers, company data, funding, technology, hiring, and account signals.
Use an agent to find patterns in recent successful deals.
Discover companies and people using a diverse range of filters and criteria.
Build dashboards, internal tools, and interactive apps on top of table data.
Execute scoring, qualification, routing, research, and waterfall logic from your own systems.
Give coding agents and MCP clients a structured interface for Clay.
## Start with routines
Most teams start by exposing a Clay function as a routine. Once a routine works, the same workflow can be called from the CLI, Public API, or MCP.
Turn Clay functions into callable routines.
# Run GTM workflows
Source: https://developers.clay.com/use-cases/run-gtm-workflows
Embed Clay scoring, routing, research, enrichment waterfalls, and other GTM logic in your systems.
Clay routines let you package GTM logic once and execute it wherever your team needs the answer. That can be a backend service, queue worker, product workflow, CRM sync, data warehouse job, or AI agent.
## Workflows Clay can run
* Waterfall enrichment across contact, company, technology, funding, and hiring data.
* Lead scoring and account prioritization using your business rules.
* Inbound routing based on fit, territory, enrichment results, or custom logic.
* Account research that combines structured data with Clay functions.
* CRM hygiene, deduping, validation, and enrichment before sync.
## Why use Clay for this
Keeping GTM logic in Clay means your team can change provider choices, prompts, scoring rules, and output fields without rewriting every downstream system. The API calls stay stable while the workflow improves.
Understand routines, runs, searches, tables, and batch jobs.
# Search Clay's GTM database
Source: https://developers.clay.com/use-cases/search-gtm-database
Use advanced queries to search Clay's proprietary database of companies and people.
Searches let your system discover GTM records without building a search UI or wiring directly into multiple data providers. Advanced search supports criteria in Clay's query reference, cross-entity filters, and nested Boolean logic.
## What you can search
| Source type | Use it for |
| - | - |
| `companies` | Accounts, domains, industries, locations, and firmographics |
| `people` | Contacts, titles, locations, and profile data |
## Example search intents
* Find B2B SaaS companies in North America with more than 1,000 employees.
* Find software engineers in New York City.
* Find software companies with more than \$250M in funding.
## Advanced search also supports cross-entity criteria
Advanced search lets you return one entity based on attributes of a related entity.
* Find sales leaders at high-growth software companies:
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
select from people where experiences.any(is_current = true and job_title is_similar_to ("VP Sales", "Head of Sales") and company.estimated_employee_count >= 500 and company.industry = "Software Development")
```
* Find engineers at companies that use Salesforce:
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
select from people where experiences.any(is_current = true and job_title is_similar_to ("engineer") and company.technographics.any(vendor = "Salesforce"))
```
* Find companies that currently employ a VP of Sales:
```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
select from companies where people.exists(is_current = true and job_title is_similar_to ("VP Sales"))
```
## How it works
Advanced search is a three-step iterator: fetch the query reference, create a search to receive a `search_id`, then fetch pages of results with that id.
Learn the search flow and copy a create-and-fetch example.