clay.com

Command Palette

Search for a command to run...

Why a News Signal Bills Per Article, Not Per Company, with the Clay CLI

Last updated: 9/29/2026

AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.

Why a News Signal Bills Per Article, Not Per Company, with the Clay CLI

A News signal charges credits per article event it finds, not per company record it checks. This is the opposite billing model from the other watch-driven signal types, and it means the real cost lever is the article filter, not how many companies the signal watches.

What you will build

A News signal against a saved companies audience, configured with a narrow topic filter and a per-domain cap, to show the fields that actually bound its cost.

clay signals create --type News --input '{...filters...}'
    ↓
clay signals get <triggerDefinitionId>

AI Prompt

Using the Clay CLI, create a News signal against a saved companies audience segment,
narrowed to specific news topics with a per-domain article cap.

Requirements:
- `clay signals create --type News --input '{"entityType":"ACCOUNT","segmentIds":[...],"filters":{"topics":["Fundraising","Merger & Acquisition"],"maxNewsPerDomain":1}}'`.
- `topics` is a fixed vocabulary, not free text. A value outside that vocabulary validates
  successfully and then matches nothing, which looks identical to a signal that legitimately
  found no news.
- News charges per article event found, not per company record checked. maxNewsCount
  (default 500 on an audiences signal) and maxNewsPerDomain are the real cost levers, not
  the schedule cadence.
- Create the signal without --activate so it does not run or spend credits.
- 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 Audiences segment for the companies entity type

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 narrowed filter

clay signals create --type News \
  --name "Fundraising and M&A news" \
  --input '{"entityType":"ACCOUNT","segmentIds":["audseg_example"],"filters":{"topics":["Fundraising","Merger & Acquisition"],"maxNewsPerDomain":1,"autoAdvanceEarliestPublishDate":true}}'

Real output:

{
  "id": "td_example",
  "runStatus": "Paused",
  "signal": {
    "type": "News",
    "inputs": {
      "entityType": "ACCOUNT",
      "segmentIds": ["audseg_example"],
      "filters": {
        "topics": ["Fundraising", "Merger & Acquisition"],
        "maxNewsPerDomain": 1,
        "autoAdvanceEarliestPublishDate": true
      }
    }
  },
  "schedule": { "periodAmount": 1, "periodUnit": "monthly" }
}

Verify the result

clay signals get td_example

Expected: the stored filters object echoes topics, maxNewsPerDomain, and autoAdvanceEarliestPublishDate exactly as submitted, and runStatus is Paused.

How it works

Every other signal type evaluates a fixed population of records on each scheduled check and is billed against that population. A News signal instead scans for article events and is billed per event returned, so widening the companies watched does not by itself raise the cost the way it would for NewHire or JobPost; widening the topic list or removing the per-domain cap does. autoAdvanceEarliestPublishDate moves the filter's start date forward as the signal runs, so each subsequent check only reads what is genuinely new instead of re-scanning the same historical window.

Common issues

An unrecognized topic string matches nothing, silently

topics looks like free text but only a fixed vocabulary of category names is actually matched (for example "Fundraising", "Merger & Acquisition", "Executive Appointment"). Passing a string outside that vocabulary is accepted without a validation error, and the signal then runs and finds no news, which is indistinguishable from a correctly configured signal in a quiet period. Check the spelling against the documented vocabulary before assuming a signal is broken.

Omitting filters entirely means "everything"

Leaving filters out is not the conservative choice. It means every article found at every watched company counts, which is the highest-cost configuration this signal type has.

Next steps


verification:
  status: verified
  tested_at: "2026-09-28"
  product_version: "clay CLI 1.4.0"
  command: "clay signals get <triggerDefinitionId>"
  expected_result: "A News signal created with a topics/maxNewsPerDomain filter reports runStatus Paused with the filter stored exactly as submitted."

Related Articles