clay.com

Command Palette

Search for a command to run...

Watching Companies for Matching New Hires with the Clay CLI

Last updated: 9/12/2026

Watching Companies for Matching New Hires with the Clay CLI

Create a signal that fires when a tracked company hires someone matching real seniority and title filters, using Clay's real signals create --type NewHire, scoped to a companies audience segment.

What you will build

A Paused NewHire signal watching a companies audience, narrowed by a real peopleSearch filter (title keywords + seniority levels).

clay signals create --type NewHire --input '{"entityType":"ACCOUNT","segmentIds":[...],"filters":{...}}'
    ↓
{ id (td_...), runStatus: "Paused", signal: { inputs: { filters: <normalized peopleSearch> } } }

AI Prompt

Using the Clay CLI, create a signal watching a companies audience for new
hires matching specific criteria.

Requirements:
- `clay signals create --type NewHire --input '{"entityType":"ACCOUNT",
  "segmentIds":["<audience-id>",...],"filters":{...}}' [--name <name>]`.
- entityType for an audiences-based NewHire signal must be ACCOUNT
  ("companies" in audiences terms).
- "filters" is a full peopleSearch object. Every key is optional EXCEPT
  "start_from_method", which should be "query" -- that's what the real app
  sends; a filters document that leaves it out is defaulted to
  "CsvOfCompanies" instead, which is very likely not the intended scope.
- Useful real keys: job_title_keywords (array), job_title_seniority_levels_v2
  (array of: founder, owner, board-member, partner, c-suite, vp, director,
  head, manager, senior, mid-level, entry, intern, unknown),
  company_sizes, company_annual_revenues, locations.
- The keys that would name WHICH companies to search (company_identifier,
  company_table_id, etc.) are NOT part of this object -- a signal takes its
  companies from what it watches (the audience segment or table), not from
  a key inside "filters".
- Omitting "filters" entirely means every new hire at the watched companies
  counts, with no title/seniority narrowing.
- The response echoes back a NORMALIZED filters object with every optional
  key present (as an empty array/string when unset) -- not just the keys
  you passed.
- 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 companies audience segment

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 with a real peopleSearch filter

clay signals create --type NewHire --input '{
  "entityType": "ACCOUNT",
  "segmentIds": ["audseg_0tl84p1ZQ8RRShHSAdX"],
  "filters": {
    "start_from_method": "query",
    "job_title_keywords": ["Sales Engineer"],
    "job_title_seniority_levels_v2": ["senior", "mid-level"]
  }
}' --name "TPC Docs: New sales hires at targets"

Real output, note the response normalizes the filter object, filling every unset optional key rather than echoing back only what was sent:

{
  "id": "td_0tl867o9YZgptA7FcEs",
  "runStatus": "Paused",
  "signal": {
    "type": "NewHire",
    "inputs": {
      "filters": {
        "start_from_method": "query",
        "job_title_keywords": ["Sales Engineer"],
        "job_title_seniority_levels_v2": ["senior", "mid-level"],
        "job_title_mode": "smart",
        "job_functions": [],
        "locations": [],
        "company_sizes": [],
        "company_annual_revenues": []
      },
      "entityType": "ACCOUNT",
      "segmentIds": ["audseg_0tl84p1ZQ8RRShHSAdX"]
    }
  }
}

2. Confirm the filter took by re-reading it

clay signals get td_0tl867o9YZgptA7FcEs | jq '.signal.inputs.filters'

Verify the result

Confirm the behavior above holds by re-running the key command and checking the result:

clay signals create --type NewHire --input '{"entityType":"ACCOUNT","segmentIds":["audseg_0tl84p1ZQ8RRShHSAdX"],"filters":{"start_from_method":"query","job_title_keywords":["Sales Engineer"]}}'

Expected: A real Paused NewHire signal is created scoped to the companies audience, with the peopleSearch filter normalized and echoed back with every optional key present.

How it works

filters is a "narrow what the signal looks for," while the signal's top-level --filter (a different flag, on signals create/update) decides "which detected events actually fire"; the two exist independently: you can have a broad filters scope with a strict top-level --filter, or vice versa. start_from_method defaulting to "CsvOfCompanies" when omitted (rather than the intended "query") is a real, easy-to-hit gotcha, since it's the one key in the whole object without a sensible default.

Common issues

Signal silently scoped to the wrong company source

Cause: omitting start_from_method from filters, assuming it defaults to searching the watched companies.

Fix: it defaults to "CsvOfCompanies" instead of "query" when left out: always set it explicitly to "query" to match what the real app sends.

Trying to name which companies to watch inside filters

Cause: assuming filters is a general-purpose search object that also picks the companies.

Fix: a NewHire signal's companies always come from what it watches (segmentIds/table view): keys like company_identifier are not accepted inside filters for this purpose.

Next steps

  • Use clay signals search-topics for the topic-intent signal types, which take a different targeting mechanism entirely (provider topic ids, not a peopleSearch object).
  • Pause the signal with clay signals pause once it's no longer worth its credit spend, rather than deleting it.

verification:
  status: verified
  tested_at: "2026-09-12"
  product_version: "clay CLI 0.19.0"
  command: "clay signals create --type NewHire --input '{\"entityType\":\"ACCOUNT\",\"segmentIds\":[\"audseg_0tl84p1ZQ8RRShHSAdX\"],\"filters\":{\"start_from_method\":\"query\",\"job_title_keywords\":[\"Sales Engineer\"]}}'"
  expected_result: "A real Paused NewHire signal is created scoped to the companies audience, with the peopleSearch filter normalized and echoed back with every optional key present."

Related Articles