clay.com

Command Palette

Search for a command to run...

Segment Id Handling When Creating a Signal 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}.

Segment Id Handling When Creating a Signal with the Clay CLI

segmentIds is an array of audience ids, and create checks each one against the workspace's audiences. Beyond the existing-id and "ALL" cases, the CLI has specific behavior for duplicate ids, mixed kinds, case, empty values, and very long lists.

What you will build

A series of signals create calls on a JobChange audience signal that vary only segmentIds, to record which forms are accepted as given, rejected, or stored unchanged.

clay signals create --type JobChange --input '{"entityType":"CONTACT","segmentIds":[<variant>]}'
    ↓
.signal.inputs.segmentIds   (exactly as submitted)   |   not_found (exit 6)   |   validation_error (exit 2)

AI Prompt

Using the Clay CLI, probe how `segmentIds` is handled by `clay signals create`.

Requirements:
- Use a JobChange signal with entityType "CONTACT" and real people segment ids.
- A duplicate id (the same id twice) is accepted and stored twice. Ids are not deduplicated.
- Two different real people segments are accepted.
- A companies segment mixed into a CONTACT list fails the whole create with validation_error.
- "ALL" is a sentinel and "ALL" twice is accepted. Lowercase "all" is looked up as a segment id
  and returns not_found (exit 6).
- An empty string returns "--input: segmentIds.0: Required". A null or a number returns
  "--input: Invalid input".
- An id with the right prefix that does not exist returns not_found (exit 6).
- A list of 200 copies of one id is accepted and stored as 200 entries.
- 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)
  • Two people segments (this doc uses audseg_0tm3lyrDBZzZgPaCsWx and audseg_0tm393zX75wpTQeAg9v) and one companies segment (audseg_0tm3nvu2EbBP6mjpk8f)

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. Every signal created here is Paused.

1. Duplicates and multiple segments

clay signals create --type JobChange --name "TPC19 seg" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3lyrDBZzZgPaCsWx"]}'

Real output, {id, seg: .signal.inputs.segmentIds}:

{"id":"td_0tmb2iw6WN6VAXN8uqm","seg":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3lyrDBZzZgPaCsWx"]}

Two different real people segments:

{"id":"td_0tmb2iyjyph7DyGDaBY","seg":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm393zX75wpTQeAg9v"]}

The duplicate id is stored twice.

2. A segment of the wrong kind

clay signals create --type JobChange --name "TPC19 seg" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3nvu2EbBP6mjpk8f"]}'
{"error":{"code":"validation_error","message":"Audience segment audseg_0tm3nvu2EbBP6mjpk8f is a ACCOUNT segment, not CONTACT"}}

The command exits 2 and creates nothing.

3. The ALL sentinel, case, and missing ids

segmentIdsResult
["ALL","ALL"]exit 0, stored as ["ALL","ALL"]
["all"]exit 6: {"error":{"code":"not_found","message":"Audience segment all not found"}}
["audseg_doesnotexist"]exit 6: {"error":{"code":"not_found","message":"Audience segment audseg_doesnotexist not found"}}
[""]exit 2: --input: segmentIds.0: Required
[null]exit 2: --input: Invalid input
[123]exit 2: --input: Invalid input

4. A very long list

A list of 200 copies of one id was generated with jq and submitted:

clay signals create --type JobChange --name "TPC19 seg" --input "$(jq -nc --arg i audseg_0tm3lyrDBZzZgPaCsWx '{entityType:"CONTACT",segmentIds:[range(200)|$i]}')"

The command exits 0 and .signal.inputs.segmentIds holds all 200 entries. No length limit was reached at 200.

Verify the result

Confirm duplicates are stored as submitted:

ID=$(clay signals create --type JobChange --name "TPC19 seg verify" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx","audseg_0tm3lyrDBZzZgPaCsWx"]}' | jq -r .id)
clay signals get "$ID" | jq -c '.input.audiences.segmentIds | length'

Expected: the output is 2.

How it works

Each id is looked up in the workspace and its kind is compared with entityType, which produces the specific not_found and kind-mismatch errors. The array itself is stored as given, with no deduplication, normalization of case, or length cap that was reached. "ALL" is exempt from the lookup because it is a sentinel.

Common issues

Duplicates are kept

["X","X"] is stored as two entries. Whether a duplicate causes a record to be checked, or billed, twice when the signal runs was not tested. Deduplicate the list before submitting.

"all" is not "ALL"

The sentinel is case-sensitive. Lowercase all is treated as an id and returns not_found.

Empty strings and null fail with different messages

[""] reports a path (segmentIds.0: Required); [null] and [123] report only Invalid input.

Next steps

  • See the existing signal targeting edge-cases doc for an empty segmentIds array and the "ALL" sentinel.
  • See the orphaned-signals doc in this batch for what happens when a listed segment is archived later.

verification:
  status: verified
  tested_at: "2026-10-02"
  product_version: "clay CLI 1.8.0+71cb1bf09c7e"
  command: "clay signals get \"$ID\" | jq -c '.input.audiences.segmentIds | length'"
  expected_result: "The output is 2, because duplicate ids are stored as submitted."

Related Articles