Watching for Promotions with the Clay CLI
?q={your_question}.Watching for Promotions with the Clay CLI
Create a signal that fires when a tracked person is promoted at their current company, using signals create --type Promotion, which shares JobChange's confidence-gated default and does not restrict which entity type it can watch.
What you will build
A Paused Promotion signal watching an audience, with the type's real default confidence filter and schedule, plus a look at its validation surface around entityType, --clear-filter, and partial updates.
clay signals create --type Promotion --input '{"entityType":"CONTACT","segmentIds":[...]}'
↓
{ id (td_...), runStatus: "Paused", filter: { confidence >= 90 }, schedule: { monthly } }
AI Prompt
Using the Clay CLI, create a signal watching for promotions.
Requirements:
- `clay signals create --type Promotion --input '{"entityType":"CONTACT",
"segmentIds":["<audience-id>",...]}' [--schedule <cadence>] [--name
<name>] [--activate]`.
- Like JobChange, Promotion ships a real default filter: confidence >= 90.
This is not an unfiltered signal by default.
- entityType "ACCOUNT" is not rejected for Promotion, even though
Promotion is conceptually a person-level event:
`signals create --type Promotion --input '{"entityType":"ACCOUNT",...}'`
succeeds (exit 0) and persists entityType: "ACCOUNT" on the signal. The
same is true for JobChange. Only PersonTopicIntent/CompanyTopicIntent
enforce an entityType restriction per the CLI's own --help; don't assume
JobChange/Promotion do too just because they're conceptually
person-scoped.
- `--clear-filter` is a flag on `signals update`, not `signals create`.
Passing it to `create` returns validation_error: "unknown option
'--clear-filter'". To remove the default confidence gate, create the
signal first, then run `signals update <id> --clear-filter`.
- lookBackTimeWindowInMonths defaults to 3 at creation. Passing it alone to
`signals update --input` (with no other key) is rejected as a
validation_error naming exactly what the type accepts ("a Promotion
signal accepts segmentIds"); it does not silently no-op. It is silently
dropped, however, when the same --input also includes a valid key like
"segmentIds".
- Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) - An existing audience segment
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. Create the signal
clay signals create --type Promotion --input '{"entityType":"CONTACT","segmentIds":["audseg_0tjs3u3yAgacWPpe926"]}' --name "TPC Batch3: Promotions"
Real output, the same confidence-gate default as JobChange:
{
"id": "td_0tlqbq5TV8dpkDpmYBi",
"runStatus": "Paused",
"signal": {"type": "Promotion", "inputs": {"lookBackTimeWindowInMonths": 3, "entityType": "CONTACT", "segmentIds": ["audseg_0tjs3u3yAgacWPpe926"]}},
"schedule": {"periodAmount": 1, "periodUnit": "monthly"},
"filter": {"type": "GroupOp", "combinationMode": "And", "items": [{"type": "BinOp", "dataPath": ["confidence"], "operator": "GreaterThanOrEqual", "value": 90}]}
}
2. Try entityType ACCOUNT: it is accepted, not rejected
clay signals create --type Promotion --input '{"entityType":"ACCOUNT","segmentIds":["audseg_0tl84p1ZQ8RRShHSAdX"]}'
Real output, exit 0, entityType persists as given:
{"runStatus": "Paused", "signal": {"type": "Promotion", "inputs": {"entityType": "ACCOUNT", "segmentIds": ["audseg_0tl84p1ZQ8RRShHSAdX"]}}}
The CLI's own create --help only documents an entityType restriction for PersonTopicIntent/CompanyTopicIntent. JobChange and Promotion accept either value even though they're conceptually person-level events.
3. Try --clear-filter on create: it doesn't exist there
clay signals create --type Promotion --input '{"entityType":"CONTACT","segmentIds":["audseg_0tjs3u3yAgacWPpe926"]}' --clear-filter
Real output:
{"error": {"code": "validation_error", "message": "unknown option '--clear-filter'"}}
Remove the default filter with a follow-up signals update <id> --clear-filter instead.
4. lookBackTimeWindowInMonths alone on update: a real error, not a silent no-op
clay signals update td_0tlqbq5TV8dpkDpmYBi --input '{"lookBackTimeWindowInMonths":6}'
Real output:
{"error": {"code": "validation_error", "message": "--input: names nothing this signal's type can change — a Promotion signal accepts segmentIds"}}
But combined with a valid key, it's accepted and silently dropped:
clay signals update td_0tlqbq5TV8dpkDpmYBi --input '{"segmentIds":["audseg_0tjs3u3yAgacWPpe926"],"lookBackTimeWindowInMonths":6}'
Exit 0, and a fresh signals get confirms lookBackTimeWindowInMonths is still 3: the extra key was accepted and ignored, not applied, only because a valid key was present alongside it.
Verify the result
Confirm the behavior above holds by re-running the key command and checking the result:
clay signals create --type Promotion --input '{"entityType":"ACCOUNT","segmentIds":["audseg_0tl84p1ZQ8RRShHSAdX"]}'
Expected: a real Paused Promotion signal is created with entityType: "ACCOUNT" persisted and no validation error, confirming Promotion does not enforce a CONTACT-only restriction despite being a person-level signal type.
How it works
Promotion and JobChange are close siblings: both detect a change in a person's employment record, both need a confidence score to separate a real detected change from noisy or ambiguous source data, and both default to the same gate for that reason. Neither type enforces an entityType restriction the way the topic-intent types do. The identifier field each type checks by, rather than entityType itself, is what determines what gets watched, so passing the "wrong" entityType doesn't cause a failure; it just may not describe the intent accurately.
Common issues
Assuming Promotion/JobChange reject entityType ACCOUNT
Both are conceptually person-level signals, and the sibling topic-intent types do enforce an entityType restriction, so it's a reasonable assumption to make. Neither JobChange nor Promotion rejects ACCOUNT, though. Only PersonTopicIntent/CompanyTopicIntent validate entityType against the type. Pass CONTACT for Promotion/JobChange because that matches what the type is for, not because ACCOUNT would be refused.
Reaching for --clear-filter on signals create
It's a real, valid flag on signals update, so it's easy to assume it's available across the whole signals command group. It only exists on update. Create the signal, then clear the filter as a follow-up call.
Assuming an out-of-shape update key always silently no-ops
Some invalid combinations in this CLI are accepted leniently, but a lone out-of-shape key (nothing else in --input) is a real validation_error. It's silently dropped only when accompanied by at least one key the type actually allows to change.
Next steps
- See the dedicated "what signals update actually changes per type" example for more on the accompanied-vs-alone distinction.
- Use
signals update <id> --clear-filterto remove the default confidence gate once the signal exists.
verification:
status: verified
tested_at: "2026-09-21"
product_version: "clay CLI 1.2.0"
command: "clay signals create --type Promotion --input '{\"entityType\":\"ACCOUNT\",\"segmentIds\":[\"audseg_0tl84p1ZQ8RRShHSAdX\"]}'"
expected_result: "The signal is created successfully (Paused, no error) with entityType ACCOUNT persisted, confirming Promotion does not enforce a CONTACT-only restriction, unlike the topic-intent signal types."