clay.com

Command Palette

Search for a command to run...

Watching an Audience for Job Changes with the Clay CLI

Last updated: 9/12/2026

Watching an Audience for Job Changes with the Clay CLI

Create a signal that fires when a tracked person's current company changes, scoped to a saved audience segment rather than a table, using Clay's real signals create --type JobChange, which ships with a real confidence filter by default.

What you will build

A Paused JobChange signal watching every contact in a saved audience, using the type's real default schedule and confidence filter.

clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":[...]}'
    ↓
{ id (td_...), runStatus: "Paused", schedule: { periodUnit: "monthly" }, filter: { confidence >= 90 } }

AI Prompt

Using the Clay CLI, create a signal watching an audience segment for job
changes.

Requirements:
- `clay signals create --type JobChange --input '{"entityType":"CONTACT",
  "segmentIds":["<audience-id>",...]}' [--schedule <cadence>] [--name
  <name>] [--activate]`.
- JobChange watches by personIdentifier and defaults to a MONTHLY schedule.
  entityType for an audiences-based signal must be CONTACT ("people" in
  audiences terms) -- ACCOUNT is rejected for this type, because the
  identifier this type checks by comes from the type itself, not from
  entityType.
- Without --input's default filter overridden by --filter, JobChange ships
  a REAL default filter: confidence >= 90 on the detected event. A signal
  that "looks unfiltered" (no --filter passed) still only fires on
  high-confidence detections -- not on every detected change.
- The signal is created Paused unless --activate is passed. Paused means it
  neither runs nor spends credits -- safe to create for inspection first.
- "ALL" as a member of segmentIds is a sentinel for the whole audience of
  that entity type, not a saved segment with that literal name.
- 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)
  • An existing people audience segment (clay audiences list --entity-type people)

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.

1. Create the signal, Paused

clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":["audseg_0tjs3u3yAgacWPpe926"]}' --name "TPC Docs: Champions moving"

Real output, created Paused, with the type's real default schedule and filter:

{
  "id": "td_0tl866woYQ5ScAFSHRP",
  "name": "TPC Docs: Champions moving",
  "runStatus": "Paused",
  "signal": {"id": "sig_0tl866wRB5EJ8XVbVbg", "type": "JobChange", "inputs": {"lookBackTimeWindowInMonths": 3, "entityType": "CONTACT", "segmentIds": ["audseg_0tjs3u3yAgacWPpe926"]}},
  "input": {"table": null, "audiences": {"segmentIds": ["audseg_0tjs3u3yAgacWPpe926"], "entityType": "CONTACT"}},
  "destinationTable": null,
  "schedule": {"periodAmount": 1, "periodUnit": "monthly", "lastRunAt": null},
  "filter": {"type": "GroupOp", "combinationMode": "And", "items": [{"type": "BinOp", "dataPath": ["confidence"], "operator": "GreaterThanOrEqual", "value": 90}]}
}

2. Confirm it before activating

clay signals get td_0tl866woYQ5ScAFSHRP | jq '{runStatus, filter}'

3. Widen or remove the confidence filter, if intended

clay signals update td_0tl866woYQ5ScAFSHRP --clear-filter

--clear-filter removes the default confidence gate entirely, so every detected job change fires regardless of confidence, a deliberate, real tradeoff between recall and noise.

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_0tjs3u3yAgacWPpe926"]}'

Expected: A real signal is created in Paused status, watching the given audience segment, carrying the type's real default monthly schedule and confidence >= 90 filter.

How it works

JobChange (and Promotion) are the only two signal types that ship a non-empty default filter; every other type (NewHire, JobPost, News, the topic-intent types) defaults to firing on every detected change. That asymmetry exists because identity-matching a "this specific person changed companies" event carries real ambiguity that a confidence score is built to capture, while "a company posted a job" or "a company appeared in the news" doesn't have an analogous confidence dimension to filter on.

Common issues

A JobChange signal that "runs but produces almost nothing"

Cause: assuming an unfiltered signals create --type JobChange (no --filter passed) fires on every detected change, since no filter was explicitly set.

Fix: JobChange and Promotion both default to confidence >= 90 even with --filter omitted: this is a real default, not an unfiltered state. Use --clear-filter (via signals update) to actually remove it.

Passing entityType: "ACCOUNT" for an audiences-based JobChange signal

Cause: assuming entityType is a free choice independent of the signal type.

Fix: JobChange watches people (CONTACT) only: ACCOUNT is rejected as a validation_error, because the type itself fixes what it watches.

Next steps

  • Resolve real topic ids first with clay signals search-topics before creating a PersonTopicIntent/CompanyTopicIntent signal.
  • Use clay signals list | jq to triage every signal in the workspace by type and run status.

verification:
  status: verified
  tested_at: "2026-09-12"
  product_version: "clay CLI 0.19.0"
  command: "clay signals create --type JobChange --input '{\"entityType\":\"CONTACT\",\"segmentIds\":[\"audseg_0tjs3u3yAgacWPpe926\"]}'"
  expected_result: "A real signal is created in Paused status, watching the given audience segment, carrying the type's real default monthly schedule and confidence >= 90 filter."