clay.com

Command Palette

Search for a command to run...

Trigger Outbound Sequences from Clay Hiring Signals via the CLI

Last updated: 9/9/2026

Trigger Outbound Sequences from Clay Hiring Signals via the CLI

Detect real hiring-momentum signals for a tracked account using the clay CLI's Company Job Openings routine, derive your own signal-strength score, and notify a sequencer via a registered webhook instead of polling.

What you will build

A CLI workflow that runs the job-openings routine, derives a signal score locally, and — for async notification instead of polling — registers a webhook the run notifies on completion.

clay webhooks create <url>                          (one-time: register your sequencer endpoint)
    ↓
clay routines runs start <id> --input '...' --webhook-id <wh-id>
    ↓
(Clay POSTs a signed event to your webhook when the run finishes)
    ↓
derive signal_strength locally from real total_job_count / recent postings

AI Prompt

Using the clay CLI, detect hiring signals for a company via Clay's
"Company Job Openings" managed function, and use a webhook instead of
polling to know when the run finishes.

Requirements:
- Find the real routine id for "Company Job Openings" via `clay routines
  list`.
- The routine's display name is "Company Job Openings" but its real result
  key is "Find Open Jobs". Within that object, the postings list is under
  the key "jobs" -- not "data".
- total_job_count can exceed the number of returned postings (capped at 10)
  -- more_matches_than_we_can_display signals when the cap was hit.
- Register a webhook with `clay webhooks create <url>` and pass its id via
  `--webhook-id` on `runs start`, so your sequencer is notified instead of
  polling.
- Derive your own 0-1 signal_strength from total_job_count and how many
  returned postings are recent -- Clay does not supply this field natively.
- Run the verification step below before finishing.

Prerequisites

  • The clay CLI on PATH, authenticated
  • An HTTPS endpoint able to receive a webhook POST (for real use; this example also shows the polling fallback if you don't have one handy)

1. Find the routine

clay routines list

Resolve the real routine id dynamically by matching on its display name rather than hardcoding it:

ROUTINE_ID=$(clay routines list | jq -r '.data[] | select(.name=="Company Job Openings") | .id')
clay routines get "$ROUTINE_ID"

Confirmed real input schema: {"Company Domain": "<hostname>"}.

2. (Optional) Register a webhook for async notification

clay webhooks create https://your-sequencer.example.com/clay-webhook

This returns a signing secret once — store it to verify incoming deliveries. See clay webhooks --help for delivery payload shape and signature verification.

clay routines runs start "$ROUTINE_ID" \
  --input '{"items":[{"id":"clay-jobs","inputs":{"Company Domain":"clay.com"}}]}' \
  --webhook-id wh_XXXXXXXXXXXXXXXXXXXX

3. Or poll directly (no webhook needed)

clay routines runs start "$ROUTINE_ID" \
  --input '{"items":[{"id":"clay-jobs","inputs":{"Company Domain":"clay.com"}}]}'
clay routines runs get <run-id> --wait 60

4. Derive the signal score locally

#!/bin/bash
RESULT=$(clay routines runs get "$1" --wait 60 | jq '.data[0].result["Find Open Jobs"]')
TOTAL=$(echo "$RESULT" | jq -r '.total_job_count')
RECENT=$(echo "$RESULT" | jq -r '[.jobs[] | select(.first_seen_at > (now - 2592000 | strftime("%Y-%m-%dT%H:%M:%SZ")))] | length')
POSTINGS=$(echo "$RESULT" | jq -r '.jobs | length')

python3 -c "
total, recent, postings = $TOTAL, $RECENT, $POSTINGS
volume = min(total / 25, 1.0)
recency = (recent / postings) if postings else 0.0
signal_strength = round(0.6 * volume + 0.4 * recency, 4)
print(signal_strength)
"

5. Verify the result

This example was tested live against clay.com.

clay routines runs start "$ROUTINE_ID" \
  --input '{"items":[{"id":"clay-jobs","inputs":{"Company Domain":"clay.com"}}]}'
{ "routineRunId": "run_0tjzn7xhMQXXcrdTmCX", "mode": "inline", "status": "in_progress" }
clay routines runs get run_0tjzn7xhMQXXcrdTmCX --wait 60

Real confirmed result:

{
  "domain": "clay.com",
  "total_job_count": 79,
  "more_matches_than_we_can_display": true,
  "jobs": [ /* 10 real postings */ ]
}

This confirms the same schema found during earlier REST testing (total_job_count=80 at that time, 79 now — real-time job-posting data legitimately changes between test runs). The postings list is genuinely under jobs, not data.

clay webhooks --help was confirmed as a real command group with create, list, delete, and test subcommands, supporting the --webhook-id async-notification pattern described above.

How it works

Company Job Openings returns real, current job postings for a domain. Because Clay doesn't supply a native "hiring signal strength," this example derives one locally from total_job_count and posting recency — an explicit, auditable scoring policy in your own script rather than something Clay computes for you.

Common issues

Postings list comes back empty despite real openings existing

Cause: reading the result under "Company Job Openings" (display name) or looking for the postings under "data" instead of "jobs".

Fix: jq '.data[0].result["Find Open Jobs"].jobs' — both the result key and the postings key must match exactly what's shown above.

total_job_count doesn't match jobs | length

Not a bug: the postings array is capped at 10 even when more exist. Check more_matches_than_we_can_display to know when the cap was hit.

Webhook never fires

Cause: --webhook-id wasn't passed on runs start, or the webhook was created but never tested.

Fix: use clay webhooks test <webhookId> to send a signed test event and confirm your endpoint receives and verifies it before relying on it for a real run.

Next steps

  • Score the qualifying accounts before triggering — see the Clay firmographic lead-scoring CLI example
  • Add recent news as a secondary signal — see the Clay company-news research CLI example
  • Build the account list feeding this pipeline — see the Clay TAM-by-industry CLI example

Verification

verification:
  status: verified
  tested_at: "2026-08-18"
  cli_version: "0.7.0"
  auth_method: "clay login --device"
  command: "clay routines runs start function:t_0tjqm9rvDhsreYq3yQr --input '{\"items\":[{\"id\":\"clay-jobs\",\"inputs\":{\"Company Domain\":\"clay.com\"}}]}' && clay routines runs get run_0tjzn7xhMQXXcrdTmCX --wait 60"
  expected_result: "domain=clay.com, total_job_count=79, more_matches_than_we_can_display=true, 10 real postings under the 'jobs' key"