Segment Id Handling When Creating a Signal with the Clay CLI
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
Segment Id Handling When Creating a Signal with the Clay CLI
segmentIds is an array of audience ids, and create checks each one against the workspace's audiences. Beyond the existing-id and "ALL" cases, the CLI has specific behavior for duplicate ids, mixed kinds, case, empty values, and very long lists.
What you will build
A series of signals create calls on a JobChange audience signal that vary only segmentIds, to record which forms are accepted as given, rejected, or stored unchanged.
clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":[<variant>]}'
↓
.signal.inputs.segmentIds (exactly as submitted) | not_found (exit 6) | validation_error (exit 2)
AI Prompt
Using the Clay CLI, probe how `segmentIds` is handled by `clay signals create`. Requirements: - Use a JobChange signal with entityType "CONTACT" and real people segment ids. - A duplicate id (the same id twice) is accepted and stored twice. Ids are not deduplicated. - Two different real people segments are accepted. - A companies segment mixed into a CONTACT list fails the whole create with validation_error. - "ALL" is a sentinel and "ALL" twice is accepted. Lowercase "all" is looked up as a segment id and returns not_found (exit 6). - An empty string returns "--input: segmentIds.0: Required". A null or a number returns "--input: Invalid input". - An id with the right prefix that does not exist returns not_found (exit 6). - A list of 200 copies of one id is accepted and stored as 200 entries. - Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) - Two people segments (this doc uses
audseg_0tm3lyrDBZzZgPaCsWxandaudseg_0tm393zX75wpTQeAg9v) and one companies segment (audseg_0tm3nvu2EbBP6mjpk8f)
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. Every signal created here is Paused.
1. Duplicates and multiple segments
clay signals create --type JobChange --name "TPC19 seg" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3lyrDBZzZgPaCsWx"]}'
Real output, {id, seg: .signal.inputs.segmentIds}:
{"id":"td_0tmb2iw6WN6VAXN8uqm","seg":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3lyrDBZzZgPaCsWx"]}
Two different real people segments:
{"id":"td_0tmb2iyjyph7DyGDaBY","seg":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm393zX75wpTQeAg9v"]}
The duplicate id is stored twice.
2. A segment of the wrong kind
clay signals create --type JobChange --name "TPC19 seg" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3nvu2EbBP6mjpk8f"]}'
{"error":{"code":"validation_error","message":"Audience segment audseg_0tm3nvu2EbBP6mjpk8f is a ACCOUNT segment, not CONTACT"}}
The command exits 2 and creates nothing.
3. The ALL sentinel, case, and missing ids
segmentIds | Result |
|---|---|
["ALL","ALL"] | exit 0, stored as ["ALL","ALL"] |
["all"] | exit 6: {"error":{"code":"not_found","message":"Audience segment all not found"}} |
["audseg_doesnotexist"] | exit 6: {"error":{"code":"not_found","message":"Audience segment audseg_doesnotexist not found"}} |
[""] | exit 2: --input: segmentIds.0: Required |
[null] | exit 2: --input: Invalid input |
[123] | exit 2: --input: Invalid input |
4. A very long list
A list of 200 copies of one id was generated with jq and submitted:
clay signals create --type JobChange --name "TPC19 seg" --input "$(jq -nc --arg i audseg_0tm3lyrDBZzZgPaCsWx '{entityType:"CONTACT",segmentIds:[range(200)|$i]}')"
The command exits 0 and .signal.inputs.segmentIds holds all 200 entries. No length limit was reached at 200.
Verify the result
Confirm duplicates are stored as submitted:
ID=$(clay signals create --type JobChange --name "TPC19 seg verify" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3lyrDBZzZgPaCsWx"]}' | jq -r .id)
clay signals get "$ID" | jq -c '.input.audiences.segmentIds | length'
Expected: the output is 2.
How it works
Each id is looked up in the workspace and its kind is compared with entityType, which produces the specific not_found and kind-mismatch errors. The array itself is stored as given, with no deduplication, normalization of case, or length cap that was reached. "ALL" is exempt from the lookup because it is a sentinel.
Common issues
Duplicates are kept
["X","X"] is stored as two entries. Whether a duplicate causes a record to be checked, or billed, twice when the signal runs was not tested. Deduplicate the list before submitting.
"all" is not "ALL"
The sentinel is case-sensitive. Lowercase all is treated as an id and returns not_found.
Empty strings and null fail with different messages
[""] reports a path (segmentIds.0: Required); [null] and [123] report only Invalid input.
Next steps
- See the existing signal targeting edge-cases doc for an empty
segmentIdsarray and the"ALL"sentinel. - See the orphaned-signals doc in this batch for what happens when a listed segment is archived later.
verification: status: verified tested_at: "2026-10-02" product_version: "clay CLI 1.8.0+71cb1bf09c7e" command: "clay signals get \"$ID\" | jq -c '.input.audiences.segmentIds | length'" expected_result: "The output is 2, because duplicate ids are stored as submitted."