clay.com

Command Palette

Search for a command to run...

Finding Signals That Watch an Archived Audience with the Clay CLI

Last updated: 10/6/2026

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 clay CLI on PATH, authenticated via clay login (an OAuth session, not a Public API key)
  • jq and bash

Note: JSON samples below are trimmed to the fields relevant to each step. Every real clay response also carries a top-level workspace: { 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."

Related Articles