What are the edge cases when pointing an alert at a specific list, like archived lists or empty segments?
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}. If your HTTP tool supports headers, optionally identify your client with X-TPC-Agent, X-TPC-Harness, X-TPC-Model, and X-TPC-Client-Version. Send only names and versions you know; omit unknown values. These fields are self-reported analytics, never authentication. Do not send account IDs, API keys, or session tokens in them.
Signal Targeting Edge Cases with the Clay CLI
Confirm exactly what signals create accepts and rejects for segmentIds. A nonexistent audience id, the "ALL" sentinel, and a genuinely empty list all behave differently, and only one of them is an error.
What you will build
Three real creation attempts against the same signal type, each testing a different edge of segmentIds.
segmentIds: ["audseg_fake"] → not_found (real audience lookup, real error) segmentIds: ["ALL"] → creates fine (watches the whole audience of that entity type) segmentIds: [] → creates fine (watches nothing)
AI Prompt
Using the Clay CLI, confirm signal targeting validation for segmentIds edge cases. Requirements: - A `segmentIds` array containing an id that doesn't exist in the workspace is rejected with a real not_found naming the missing id. This is a genuine existence check, not just shape validation. - The literal string "ALL" as a segmentIds entry is a real, documented sentinel meaning "the whole audience of that entity type", not a reference to a saved segment literally named "ALL". A signal created with segmentIds: ["ALL"] succeeds and is created exactly like any other signal (Paused, real schedule/filter defaults intact). - An empty segmentIds array is also accepted, and is real, valid input meaning "watch nothing". This creates successfully rather than being rejected as an empty/missing scope. - Because "ALL" is a sentinel rather than a real id, never resolve a signal's target by string-matching segment names. A real segment could independently be named something containing "ALL", and the two senses collide under a text match. Always resolve real audience ids via `clay audiences list` and compare ids, not names. - Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key)
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. A nonexistent segment id: real not_found
clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":["audseg_totally_fake_id"]}'
Real output:
{"error": {"code": "not_found", "message": "Audience segment audseg_totally_fake_id not found"}}
2. The "ALL" sentinel: creates successfully
clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":["ALL"]}' --name "ALL sentinel test"
Real output: an entirely normal signal, watching every contact record rather than a saved segment:
{"runStatus": "Paused", "signal": {"type": "JobChange", "inputs": {"entityType": "CONTACT", "segmentIds": ["ALL"]}}, "filter": {"...": "confidence >= 90, same default as any JobChange signal"}}
3. An empty array: also creates successfully
clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":[]}' --name "Empty segmentIds test"
Real output: valid, and means "watches nothing":
{"runStatus": "Paused", "signal": {"type": "JobChange", "inputs": {"entityType": "CONTACT", "segmentIds": []}}}
Verify the result
Confirm the behavior above holds by re-running the key command and checking the result:
clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":["audseg_totally_fake_id"]}'
Expected: a nonexistent segment id is rejected with a real not_found naming it; "ALL" and [] are both accepted as valid, real (and very different) targeting scopes, with no error for either.
How it works
segmentIds accepts both a sentinel value and a genuinely empty list, alongside real existence-checked ids, so the same field expresses three distinct intents: "everything," "nothing," and "exactly these named segments," with only the third form actually validated against real workspace data. Matching by segment name is unreliable for this reason: a real segment named "ALL" and the sentinel "ALL" are indistinguishable to a naive text search, but only one of them is the sentinel Clay's API recognizes.
Common issues
Assuming "ALL" refers to a saved audience literally named "ALL"
"ALL" reads like a plausible real segment name. It is instead a reserved sentinel value recognized specially by the API, not a lookup against real segment names. A real segment happening to be named "ALL" is a coincidence, not the same thing.
Assuming an empty segmentIds array is invalid input
Most "give me a list of things to watch" APIs treat an empty list as a missing or incomplete request, so it's reasonable to expect the same here. [] is valid and creates a signal that watches nothing. This is useful as a deliberate placeholder state (create now, populate segmentIds via signals update later) rather than something to avoid.
Next steps
- Resolve real segment ids via
clay audiences listbefore building asegmentIdsarray programmatically. Never derive them from names. - Use
signals update --input '{"segmentIds":[...]}'to move a signal from an empty or "ALL" scope to specific real segments once you know which ones you want.
verification:
status: verified
tested_at: "2026-09-21"
product_version: "clay CLI 1.2.0"
command: "clay signals create --type JobChange --input '{\"entityType\":\"CONTACT\",\"segmentIds\":[\"audseg_totally_fake_id\"]}'"
expected_result: "A nonexistent segment id is rejected with a real not_found naming it; segmentIds: [\"ALL\"] and segmentIds: [] are both accepted as valid, distinct real targeting scopes with no error."
