Table-Scoped Signal Targeting and Its CLI Limitation
?q={your_question}.Table-Scoped Signal Targeting and Its CLI Limitation
Understand the second way to scope a signal, watching a Clay table view instead of an audience segment, and a gap in CLI coverage: there is no CLI command that discovers a table's real viewId, so this targeting mode (and the related --destination-table option) can only be fully exercised from the Clay app.
What you will build
A real error demonstrating the gap, plus the exact request shape you'd use if you had a real view id from the app.
clay tables columns list <tableId> (real column ids, this works)
↓
clay signals create --type NewHire --input '{"tableId":...,"viewId":<no CLI source>,...}'
↓
not_found: "View: <id> not found for table: <tableId>" ← returned for any id not sourced from the app
AI Prompt
Using the Clay CLI, understand table-scoped signal targeting and its real limitation. Requirements: - Every signal type accepts TWO targeting modes: audiences (segmentIds) or a table view (tableId + viewId + an identifier field). The examples in this series all use audiences scope because of the following limitation. - A table-scoped signal's "viewId" refers to a saved view on a Clay table, a UI-level concept. No `clay tables` subcommand (list, get, columns, rows, query, query-live, query-usage, update) returns or lists view ids. There is no CLI discovery path for this value. - Passing any id not sourced from the Clay app for --viewId (or the equivalent JSON field) returns a real, specific not_found: "View: <id> not found for table: <tableId>". This is a hard requirement, not a soft validation that can be routed around. - `--destination-table <tableId>` (write a table-scoped signal's events into an existing table instead of a fresh one) is ALSO restricted to table-watching signals only, so it inherits the same viewId prerequisite and cannot be demonstrated end-to-end from the CLI alone either. - `clay tables columns list <tableId>` DOES work from the CLI, and is useful for preparing the identifier field (companyIdentifier/ personIdentifier) you'd need once you have a real view id. - Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) - A real Clay table (discoverable via
clay tables list)
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. Discover a real table and its columns
clay tables list clay tables columns list <tableId>
Real output for a real workspace table, with usable column ids for an identifier field:
{"data": [{"id": "f_0tjkv31Jri8k7NNg8Up", "name": "Domain"}]}
2. Attempt a table-scoped signal without a real view id
clay signals create --type NewHire --input '{
"tableId": "<tableId>",
"viewId": "view_fake_test",
"companyIdentifier": {"fieldId": "f_0tjkv31Jri8k7NNg8Up", "pathAsFormula": "{{f_0tjkv31Jri8k7NNg8Up}}"}
}' --name "Table-view test"
Real output, exit code 6:
{"error": {"code": "not_found", "message": "View: view_fake_test not found for table: <tableId>"}}
3. What you'd run with a real view id (from the Clay app)
clay signals create --type NewHire --input '{
"tableId": "<tableId>",
"viewId": "<real-view-id-from-the-app>",
"companyIdentifier": {"fieldId": "f_0tjkv31Jri8k7NNg8Up", "pathAsFormula": "{{f_0tjkv31Jri8k7NNg8Up}}"}
}' --destination-table <existing-tableId>
This shape is correct per the schema, but wasn't executed live in this example, since there is no CLI-discoverable viewId to substitute.
Verify the result
Confirm the behavior above holds by re-running the key command and checking the result:
clay signals create --type NewHire --input '{"tableId":"<real-table-id>","viewId":"view_fake_test","companyIdentifier":{"fieldId":"<real-field-id>","pathAsFormula":"{{<real-field-id>}}"}}'
Expected: a viewId not sourced from the Clay app returns a real not_found error naming the id and table, confirming the requirement is enforced server-side and not something a CLI-only workflow can construct around.
How it works
Table views (saved filters/sorts on a table, visible and manageable in the Clay app's UI) are managed through the Clay app's UI, and the CLI's table-management surface currently exposes columns, rows, and query access but not view management. This is a current gap between what the CLI surface covers and what the underlying product supports; audiences-scoped targeting is the CLI-native path for this reason.
Common issues
Assuming a table's default/main view has a guessable or fixed id
Some Clay resources have predictable id patterns, which can suggest a view id might follow the same pattern. There's no way to derive or list a view id from the CLI. It must come from the Clay app (e.g. copied from the view's URL or the app's own signal-creation flow).
Conflating this limitation with a signal-creation validation failure
The error can look like ordinary input validation. It's a real not_found, not a validation_error. The request shape is otherwise correct; only the view genuinely doesn't exist as far as the API is concerned.
Next steps
- Use audiences-scoped targeting (
entityType+segmentIds) for anything you need to build and verify entirely from the CLI. Every other example in this series does. - If table-scoped targeting is a hard requirement, create the view in the Clay app first, then use this same request shape with the app-sourced
viewId.
verification:
status: verified
tested_at: "2026-09-21"
product_version: "clay CLI 1.2.0"
command: "clay signals create --type NewHire --input '{\"tableId\":\"t_0tjkv30Hz8FNG6j5g8Q\",\"viewId\":\"view_fake_test\",\"companyIdentifier\":{\"fieldId\":\"f_0tjkv31Jri8k7NNg8Q\",\"pathAsFormula\":\"{{f_0tjkv31Jri8k7NNg8Q}}\"}}'"
expected_result: "A viewId not sourced from the Clay app returns a real not_found naming the id and table, confirming there is no CLI-only path to fully exercise table-scoped signal targeting or --destination-table."