Finding Signals That Watch an Archived Audience with the Clay CLI
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
Finding Signals That Watch an Archived Audience with the Clay CLI
Archiving an audience does not change the signals that watch it. They keep their segmentIds, stay in their previous run status, and report no error, while the audience disappears from clay audiences list and clay audiences get. A short script can join the two listings to find these orphaned signals.
What you will build
A script, find-orphaned-signals.sh, that lists every audience signal whose segmentIds include an id no longer returned by clay audiences list, followed by a repair using clay signals update --input.
clay audiences list (companies + people) ──► live segment ids
clay signals list ──► signals with audiences
──► segmentIds not in the live set and not "ALL" = orphans
AI Prompt
Using the Clay CLI, find signals that watch audiences which have been archived.
Requirements:
- `clay audiences archive <id>` is a soft delete: archived audiences stop appearing in
`clay audiences list`, and `clay audiences get <id>` returns not_found (exit 6).
- A signal that watches an archived audience is not changed. `clay signals get` still shows the
archived id in `input.audiences.segmentIds`, `runStatus` is unchanged, and `error` is null.
- Creating a new signal on an archived audience returns not_found (exit 6).
- `clay audiences list` requires `--entity-type people|companies`, so list both and combine.
- "ALL" is a sentinel, not an audience id; exclude it from the comparison.
- To repair, `clay signals update <id> --input '{"segmentIds":[...]}'` replaces the list.
- Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) jqand bash
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. The audience and signals here are throwaway.
1. Archive an audience that a signal watches
AUD=$(clay audiences create --entity-type companies --name "TPC19 throwaway audience" --filter '{"type":"GroupOp","combinationMode":"And","items":[]}' | jq -r .id)
SIG=$(clay signals create --type News --name "TPC19 watches throwaway" --input "{\"entityType\":\"ACCOUNT\",\"segmentIds\":[\"$AUD\"]}" | jq -r .id)
clay audiences archive $AUD
Real output of the archive:
{"ok":true}
2. What the signal and audience report afterward
clay signals get td_0tmb2snkZV8QJHEYRSR | jq -c '{runStatus,input,error}'
clay audiences list --entity-type companies | jq -c '[.data[]|select(.id=="audseg_0tmb2sm9RmRr4Waxhe4")]'
clay audiences get audseg_0tmb2sm9RmRr4Waxhe4
Real output, in order. The signal is unchanged, before and after the archive:
{"runStatus":"Paused","input":{"table":null,"audiences":{"segmentIds":["audseg_0tmb2sm9RmRr4Waxhe4"],"entityType":"ACCOUNT"}},"error":null}
The archived audience is absent from the listing, and audiences get fails:
[]
{"error":{"code":"not_found","message":"No audience with id audseg_0tmb2sm9RmRr4Waxhe4"}}
A new signal on the archived id is also refused:
{"error":{"code":"not_found","message":"Audience segment audseg_0tmb2sm9RmRr4Waxhe4 not found"}}
3. The audit script
#!/usr/bin/env bash
# find-orphaned-signals.sh
set -euo pipefail
{ clay audiences list --entity-type companies; clay audiences list --entity-type people; } \
| jq -s '[.[].data[].id]' > /tmp/live-segments.json
clay signals list | jq -r --slurpfile live /tmp/live-segments.json '
.data[] | select(.input.audiences != null)
| . as $s
| ($s.input.audiences.segmentIds | map(select(. != "ALL" and (. as $x | $live[0] | index($x)) == null))) as $dead
| select($dead | length > 0)
| [$s.id, $s.signal.type, $s.runStatus, ($dead | join(","))] | @tsv'
4. Find an orphan, repair it, and re-audit
On a workspace with no orphans the script prints nothing and exits 0. A signal was then created on a throwaway audience plus a live one, and that audience was archived:
AUD=$(clay audiences create --entity-type companies --name "TPC19 orphan demo" --filter '{"type":"GroupOp","combinationMode":"And","items":[]}' | jq -r .id)
SIG=$(clay signals create --type News --name "TPC19 orphan demo" --input "{\"entityType\":\"ACCOUNT\",\"segmentIds\":[\"$AUD\",\"audseg_0tm3nvu2EbBP6mjpk8f\"]}" | jq -r .id)
clay audiences archive $AUD
./find-orphaned-signals.sh
Real output (tab-separated: signal id, type, run status, dead segment ids):
td_0tmb36bCUaJqzN3xfRa News Paused audseg_0tmb36aNgTTA2KFemv8
Repair by replacing the list with only the live id, then re-run the audit:
clay signals update td_0tmb36bCUaJqzN3xfRa --input '{"segmentIds":["audseg_0tm3nvu2EbBP6mjpk8f"]}' | jq -c '{id,seg:.signal.inputs.segmentIds}'
./find-orphaned-signals.sh; echo "exit $?"
{"id":"td_0tmb36bCUaJqzN3xfRa","seg":["audseg_0tm3nvu2EbBP6mjpk8f"]}
The audit then prints nothing and exits 0.
Verify the result
Confirm the audit reports an orphan and then reports clean after the repair, as in step 4:
./find-orphaned-signals.sh | wc -l
Expected: the count is 1 while the archived audience's id is in a signal's segmentIds, and 0 after that id is replaced.
How it works
clay audiences list returns only live audiences, so the set of ids it returns is the set a signal can still resolve. Signals store segment ids by value and are not rewritten when an audience is archived, so the join between the two listings is the only place the mismatch shows up. The "ALL" sentinel is excluded because it is not a saved audience.
Common issues
An orphaned signal shows no error
runStatus stays Paused or Active and error is null. Whether an Active signal on an archived audience keeps running, errors, or watches nothing was not tested, because activating a signal starts spend.
A signal with one dead id and one live id is still an orphan
The script reports it with only the dead ids. The live id keeps working as a target, so the repair removes only the dead id.
audiences list needs an entity type
The command fails with required option '--entity-type <type>' not specified if the flag is omitted, so the script lists companies and people separately.
Table-watching signals are not checked
The script selects signals with .input.audiences. A signal that watches a table view has .input.table and is skipped.
Next steps
- See the duplicate-signals doc in this batch for another audit built on
signals list. - See the existing doc on archiving stale audiences for the audience side of this workflow.
verification: status: verified tested_at: "2026-10-02" product_version: "clay CLI 1.8.0+71cb1bf09c7e" command: "./find-orphaned-signals.sh | wc -l" expected_result: "The count is 1 while an archived audience's id is in a signal's segmentIds, and 0 after that id is replaced."