clay.com

Command Palette

Search for a command to run...

How Topic-Intent Signals Are Billed 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}.

How Topic-Intent Signals Are Billed with the Clay CLI

A PersonTopicIntent or CompanyTopicIntent signal charges credits on every scheduled check, once per record checked, per topic, per provider, whether or not any intent is actually detected. This makes it the most expensive signal type to leave broadly configured.

What you will build

A CompanyTopicIntent signal watching a saved audience segment for two intent providers at once, so the real created object shows how the provider list and topic list combine into the billing surface.

clay signals search-topics                  (resolve a topic name to a provider-specific id)
    ↓
clay signals create --type CompanyTopicIntent   (attach the id to one or more providers)
    ↓
clay signals get <triggerDefinitionId>          (inspect the stored config)

AI Prompt

Using the Clay CLI, create a CompanyTopicIntent signal against a saved audience segment,
watching one topic across two intent providers.

Requirements:
- Resolve a real topic id first with `clay signals search-topics --query "<text>" --entity-type company`.
  Provider ids are opaque and provider-specific: copy an id only into a providerConfig for
  the same provider.
- `clay signals create --type CompanyTopicIntent --input '{"entityType":"ACCOUNT","segmentIds":[...],"providerConfigs":[{"provider":"intentsify","topicIds":["<id>"],"tiers":["high"]},{"provider":"bombora","topicIds":["<topic name>"]}]}'`.
  bombora's topic catalog has no stable ids: its topicIds are the literal topic names.
- Every run of this signal charges per record checked, per topic, per provider, regardless
  of whether intent comes back. A config with an empty or missing topicIds list has no
  topic filter at all (it matches every topic the provider tracks) and is still charged as
  one topic per provider.
- 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. Resolve a real topic id per provider

clay signals search-topics --query "hiring plans" --entity-type company

Real output, trimmed to the first match:

{
  "data": [
    {
      "name": "Hiring Assessment",
      "score": 0.629,
      "matchType": "semantic",
      "matches": {
        "delivr": [],
        "intentsify": [{ "id": "48702", "name": "Hiring Assessment" }],
        "bombora": []
      }
    }
  ]
}

Each provider's matches array is that provider's own equivalent of the topic, with its own id. An empty array under a provider means that provider has no equivalent for this topic at all, which is different from a topic that exists but matched nothing.

2. Create a signal with two providers on one topic

clay signals create --type CompanyTopicIntent \
  --name "Hiring intent (multi-provider)" \
  --input '{"entityType":"ACCOUNT","segmentIds":["audseg_example"],"providerConfigs":[{"provider":"intentsify","topicIds":["48702"],"tiers":["high"]},{"provider":"bombora","topicIds":["Sales Intelligence"]}]}'

Real output:

{
  "id": "td_example",
  "name": "Hiring intent (multi-provider)",
  "runStatus": "Paused",
  "signal": {
    "type": "CompanyTopicIntent",
    "inputs": {
      "providerConfigs": [
        { "provider": "intentsify", "topicIds": ["48702"], "tiers": ["high"] },
        { "provider": "bombora", "topicIds": ["Sales Intelligence"] }
      ],
      "entityType": "ACCOUNT",
      "segmentIds": ["audseg_example"]
    }
  },
  "schedule": { "periodAmount": 1, "periodUnit": "weekly" }
}

Two providerConfigs entries mean every checked record is evaluated twice, once per provider, each against its own topic list. tiers narrows by intent strength (low/medium/high) and defaults to all three when omitted.

Verify the result

Confirm the signal was created Paused, so it neither runs nor spends credits until explicitly activated:

clay signals get td_example

Expected: "runStatus": "Paused", with both provider configs echoed back exactly as submitted.

How it works

A topic-intent signal's cost surface has three independent multipliers: the number of records the schedule checks, the number of topics each provider config lists, and the number of providers configured. A config with no topic filter is still counted as one topic per run, since "watch everything" is not the same as "watch nothing." Weekly is both the default and the fastest schedule this signal type accepts, matching how often the underlying intent providers refresh their own data.

Common issues

An empty or missing topicIds list is not a no-op

Leaving topicIds out, or passing an empty array, does not disable that provider's charge. It means the provider has no topic filter and matches everything it tracks, and is still billed as one topic for that provider on every run.

Providers cannot be added or removed after creation

Each provider carries its own detection baseline, so the set of providers is fixed at creation. clay signals update can change an existing provider's topicIds and tiers, but adding or dropping a provider entry returns a validation_error. A different provider mix requires a new signal.

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 CompanyTopicIntent signal created without --activate reports runStatus Paused, with both provider configs stored exactly as submitted."

Related Articles