# Company Signals Monitor: Hiring, Ads, Tech and News Changes (`accountable_eel/company-signals-monitor`) Actor

Turn company domains into an account watchlist: one row per company with what changed since the last run. Buying signals from hiring and ads changes, tech stack moves and news. Alerts to Slack, Discord or Telegram, or to Google Sheets or Clay. Only companies a signal answered for are billed.

- **URL**: https://apify.com/accountable\_eel/company-signals-monitor.md
- **Developed by:** [Adrian Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.20 / 1,000 company checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Company Signals Monitor: Hiring, Ads, Tech and News Changes

Paste a list of company domains. Every run comes back with one row per company saying what that
company is doing now **and what moved since the last time you checked**: roles opened and closed, ad
platforms switched on and off, technologies added and dropped, and the news published in between.
One number per company, 0 to 100, ranks the list for you.

### Who it's for

Anyone who keeps a list of companies and needs to know when something happens on it.

- **Sales and account research.** 200 target accounts, checked every morning. The four that started
  hiring salespeople and switched on LinkedIn ads this week are the four worth a call today.
- **Agencies and consultancies.** A prospect that just added HubSpot, started running Google Ads and
  opened three marketing roles is buying the thing you sell, this quarter.
- **Competitive watching.** Where is a competitor hiring, what did they just put on their site, and
  when did they start advertising.
- **Recruiters.** Companies opening roles in your niche, with the board link and the department mix
  on the row.
- **Anyone building a list.** Feed it the output of a company-finding step and let it score and
  re-score the list on a schedule.

### What a watchlist run gives you

The first run for a company is its **baseline**: you get the current picture, the changes are empty,
and `firstRun` is `true`. From the second run on, every row carries both.

| | Now | Since the last run |
|---|---|---|
| **Hiring** | open roles, top departments, the job board link, the job system | roles added, roles closed, the percentage change |
| **Ads** | running on Google / LinkedIn / Meta, and how many ads each | platforms newly started, platforms stopped |
| **Tech** | the technologies on the homepage | added, removed |
| **News** | the three newest headlines with links and dates | how many articles since the last check |

Plus `signalScore` (0 to 100), `changedSignals` (which of the four moved), `lastCheckedAt`, and a
plain-English `note` whenever anything about the row needs explaining.

### The four signals

**Hiring.** We find the company's job board ourselves from its own website: a board link or embed on
the homepage, then `/careers`, `/jobs`, `/karriere`, `/join-us` and careers-looking links, then, if
nothing names a board, one probe per job system with a name derived from the domain. Ten systems are
read: Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Personio, Recruitee, Teamtailor, Workday
and iCIMS. A board found by probing that turns out to belong to a **different** company is rejected,
not reported.

**Ads.** Google's own Ads Transparency Center (by domain, which is exact), the LinkedIn Ad Library
(by brand name) and Meta's Ad Library API (by brand name, and only with your own token). Each
platform answers for itself: one being rate-limited never affects the other two.

**Tech.** The company's homepage HTML and its response headers, matched against 37 high-precision
fingerprints across ecommerce, CMS, frameworks, analytics, marketing, chat, CDN, hosting, payments
and bot protection. A page that merely *mentions* a product is not a match; the fingerprint has to
be a real asset path, script variable or header.

**News.** Google News, searched for the company's name **and** its domain together, over exactly the
window since your last check (capped at one week). A quiet week comes back as `0`, which is a real
answer, not a blank.

### The signal score, in full

0 to 100, and deliberately split in two halves so you can read it at a glance.

The first **40 points describe the company as it is now**. They are available on the very first run,
when there is nothing to compare against:

| Component | Max | How |
|---|---|---|
| Open roles | 15 | 1 point per open role, capped at 15 |
| Ad platforms live | 10 | 5 points per platform running ads, capped at 10 |
| News this window | 15 | 5 points per article since the last check, capped at 15 |

The other **60 points describe movement** since the previous run, and are 0 on a first run:

| Component | Max | How |
|---|---|---|
| Roles added | 30 | 6 points per new open role, capped at 30 |
| Ad platforms newly started | 20 | 10 points per platform that switched ads on, capped at 20 |
| Tech stack moved | 10 | 5 points per technology added or removed, capped at 10 |

So **a score at or below 40 means nothing moved** — it is just the current picture — and every point
above 40 is a real change since you last looked. `firstRun` on the row tells you which of the two a
score belongs to.

Roles **closed** and ad platforms **stopped** are reported on the row but score nothing. They are
the interesting half of a churn story, but they are not buying signals, and counting them would let
a company shedding its whole engineering team outrank one that is hiring.

### What "changed" is allowed to mean

A monitor is only as good as its willingness to say "I don't know". Three rules, and there are unit
tests for each of them:

1. **A signal that could not be read is never a change.** If the LinkedIn Ad Library returns 403,
   that company did not "stop advertising on LinkedIn" — the column comes back empty, `adsStopped`
   stays empty, and the note says LinkedIn did not answer. The previous answer is kept, so the run
   *after* the failure can still report a real change.
2. **Roles closed is withheld unless both runs read the whole board.** On a board bigger than the
   pages we read, a role sliding onto a later page would look closed. `rolesRemovedSinceLast` comes
   back empty instead, and the note says why. Roles *added* is still reported, because a new posting
   id is a new posting id either way.
3. **A company that moves to a different job board re-baselines.** The old and new boards have
   completely different posting ids, so comparing them would report every role as both closed and
   new at once. Hiring re-baselines for that company, and the note says so.

### Alerts to Discord, Slack or Telegram

Paste a Discord or Slack webhook, a Telegram bot link, or any https link of your own into **Send an
alert to this link**, and every company whose signals moved is posted there as it is found, with the
score, what changed and the newest headline. Companies with nothing new are never posted.

Alerts are free and never change what a run costs. The link is stored encrypted, never written into
your results, and stripped out of every message this actor writes. Above the per-run cap, the rest
are folded into one "+N more" summary message.

### What a run costs, and how to control it

The price is per company, and the same whichever signals you keep — but **dropping a signal is what
makes a run cheaper and faster**, because the requests behind it are simply not made. Hiding a
column is not: it only changes what the table shows.

- **Only want new job postings?** Keep `hiring` and drop the other three.
- **Only want ad changes?** Keep `ads`.
- **Watching a long list?** `hiring` and `tech` share one request to the company's homepage between
  them, so keeping both costs barely more than keeping one.

A **quiet re-check is charged the same as a busy one**: the same requests to the same four targets
were made either way, and "nothing changed this week" is the answer you are paying for. What is
never charged is a company where **every** selected signal failed to answer — that row comes back
`found: false` with a message saying what each one reported, and costs nothing.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `domains` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~company-signals-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"domains":["notion.com","hubspot.com"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

### Input

```json
{
  "domains": [
    "notion.com",
    "hubspot.com"
  ]
}
```

One company domain per line. A careers-page URL or a job-board URL works too. Run the same list on a schedule and every row tells you what changed since the run before. Accepted formats: notion.com, https://www.hubspot.com, https://stripe.com/jobs.

Three more things worth filling in:

- **Watchlist name.** This is what keeps two schedules apart. Two lists sharing a name share one
  memory, so each would tell the other's companies that everything changed.
- **Company names**, one per domain, in the same order. LinkedIn and Meta match ads by brand name
  rather than by domain, and Google News searches better with a real name.
- **Which signals to check.** All four by default.

### Output

One row per company.

| query | found | status | domain | companyName | openRoles | rolesAddedSinceLast | rolesRemovedSinceLast | hiringGrowthPct | topHiringDepartments | careersUrl | atsName | adsGoogle | adsLinkedin | adsMeta | adsStarted | adsStopped | adsCounts | sampleAdUrls | techStack | techAdded | techRemoved | newsCountSinceLast | latestHeadlines | newsWindowHours | signalScore | changedSignals | firstRun | hiringStatus | adsStatus | techStatus | newsStatus | lastCheckedAt | note | notifyErrors | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| notion.com | true | OK | <company domain> | <company name> | <open roles now> | <new roles since last run> | <roles closed since last run> | \<change in open roles (%)> | <top hiring departments> | <job board> | <job system> | \<running google ads?> | \<running linkedin ads?> | \<running meta ads?> | <started advertising on> | <stopped advertising on> | <ads live per platform> | <sample ad links> | <tech stack now> | <tech added since last run> | <tech removed since last run> | <news articles since last run> | <latest headlines> | \<news window (hours)> | \<signal score (0 to 100)> | <what changed> | \<first run for this company?> | <hiring check result> | <ads check result> | <tech check result> | <news check result> | <previously checked> | <note> | <alert delivery problems> | 1970-01-01T00:00:00.000Z |

A company where every selected signal failed comes back as a row with `"found": false`, a `message`
saying what each one reported, and no charge.

Two ready-made views on the results: **Signals now** (the current picture) and **What changed** (the
delta columns only).

### Example runs

Three inputs that need no credentials of any kind and return rows as they stand. Paste one into the
Input tab and press Start.

**1. A morning watchlist over your target accounts**

```json
{
  "domains": ["notion.com", "hubspot.com", "figma.com"],
  "deltaName": "target-accounts"
}
```

**2. New job postings only, across a list of companies**

```json
{
  "domains": ["notion.com", "hubspot.com", "stripe.com", "canva.com"],
  "signals": ["hiring"],
  "deltaName": "hiring-watch"
}
```

**3. Who just started advertising**

```json
{
  "domains": ["hubspot.com", "notion.com", "monday.com"],
  "signals": ["ads", "news"],
  "deltaName": "ads-watch"
}
```

Run any of them twice, a day or a week apart, and the second run is where the change columns fill in.

### Pricing

Pay-per-event. A flat per-run fee covers session/proxy warmup; each independent
source is billed under its own event, only when that source actually returns
data — see `.actor/pay_per_event.json` for exact prices. A miss is never
charged.

Concretely: one charge per company, once, when at least one of the signals you selected returned
data. A company where every selected signal failed to answer is billed nothing. A quiet re-check is
billed the same as a busy one, because the same checks were made.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~company-signals-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"domains":["notion.com","hubspot.com"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~company-signals-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"domains":["notion.com","hubspot.com"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~company-signals-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"domains":["{{company}}"]}`, mapping the row's company into the `domains` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Company buying signals: hiring, ads, tech and news" — the agent will find and run this actor.

### vs. the alternatives

| | What it does | What it doesn't |
|---|---|---|
| **This actor** | Four signals per company in one row, plus what changed since your last run, plus a score and a webhook alert | It is a watchlist, not a database: it reads the four sources live on every run, so the first run is always a baseline |
| A hiring-signal or ads-presence tool on its own | One signal, in more depth (every job row, every ad creative) | No cross-signal view, and no notion of "since last time" |
| A sales-intelligence platform | Firmographics, contacts, intent data, a seat-priced subscription | Rarely tells you *what changed this week* on your own list, and never for a fraction of a cent per company |
| A tech-stack lookup | A broader fingerprint list | One reading, no history, no hiring or ads |

### Limits, stated plainly

- **The first run for a company is always a baseline.** There is nothing to compare it against.
  Schedule the same input and the second run onwards is where the value is.
- **A named watchlist is how the memory works.** Two different lists under the same name will tell
  each other's companies that everything changed. Name them separately.
- **News reaches back one week at most**, even if the watchlist has not run for a month.
- **Meta needs your own Ad Library API token.** Without one the Meta column stays empty. Outside the
  EU and UK, Meta's official API only covers political and issue ads, not ordinary commercial ones.
- **LinkedIn and Meta match by brand name**, not by domain, so fill in the company names for a
  company whose brand does not match its domain.
- **Workday boards are only found from a link on the company's own site.** Paste the careers-page URL
  for a company you know is on Workday.
- **The tech reading is of the homepage**, not of every page on the site, and covers 37 fingerprints
  rather than every product on the market.
- **Open roles can be an estimate** on a very large board, and the row says so.

### Data and privacy

Everything read here is **public company information**: a company's own website and careers pages,
its job board's public listing feed, the ad-transparency libraries the platforms publish by law, and
Google News. No personal data about individuals is collected, and nothing is read behind a login.

Your Meta token and your alert link are both stored encrypted, are never written into your results,
and are stripped out of every message and error this actor produces. The watchlist memory stores
only what it needs to compare two runs: job posting ids, which ad platforms were running,
technology names, and a timestamp.

### FAQ

**Why is my first run's score so low?**
Because 60 of the 100 points measure change, and a first run has nothing to change against. A first
run maxes out at 40. Run it again tomorrow.

**Can I get an alert only when something happens?**
Yes, two ways, and they are independent. Turn on **Only return companies where something changed**
to leave quiet companies out of the results, and paste a webhook link to have the changed ones
pushed to Discord, Slack or Telegram as they are found.

**Does hiding columns make it cheaper?**
No. Dropping a **signal** does, because the requests behind it are not made. Columns only change
what the table shows.

**Why does a company show no job board when I know it is hiring?**
Most often it is on Workday, which can only be found from a link on the company's own site. Paste
the careers-page URL instead of the bare domain. Occasionally a company's careers page is built so
that its board is loaded by a script we cannot see, and the note will say how many pages were read.

**Is `adsMeta` empty because the company runs no Meta ads?**
Only if you supplied a token. Without one, the column is empty because the check could not be made,
and the note says so. Empty never means "no" on any of the three ad columns: a platform that did not
answer is empty, and only a platform that answered gets a `true` or a `false`.

**Can two schedules share a watchlist name?**
They can, but they should not. The name is the memory, so two lists sharing one would each report
the other's companies as changed.

**How often should I run it?**
Daily is the sweet spot for hiring and ads. Weekly is plenty for tech stacks. Anything less often
than weekly and the news window starts truncating.

### Related actors

- **Company Hiring Signals** — the hiring signal on its own, in full depth: every open role as its
  own row, locations, remote share and posting ages.
- **Ads Presence Unified Lookup** — Google, LinkedIn and Meta ad presence on its own, with counts
  and sample creatives per platform.
- **Website Tech Stack Detector** — the tech reading on its own, with the category of every
  technology found.
- **Google News Lookup** — any Google News search as a list of articles, with its own monitoring
  mode.
- **Company Domain Enrichment** — the step before this one: turn a company name into a domain, then
  watch it here.

# Actor input Schema

## `domains` (type: `array`):

One company domain per line. A careers-page URL or a job-board URL works too. Run the same list on a schedule and every row tells you what changed since the run before. Accepted formats: notion.com, https://www.hubspot.com, https://stripe.com/jobs. You're only charged for the ones we actually find — a miss costs nothing.

## `companyNames` (type: `array`):

Optional, in the same order as the domains above. LinkedIn and Meta match ads by brand name rather than by domain, and Google News searches better with a real name, so filling this in makes those two signals more accurate. Leave it empty and we derive a name from the domain and from the company's own site.

## `signals` (type: `array`):

All four by default. Dropping a signal is what makes a run cheaper and faster; hiding a column is not. The price per company is the same whichever signals you keep.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

## `maxResults` (type: `integer`):

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `deltaName` (type: `string`):

Name your watchlist, e.g. "target-accounts" or "competitors". The name is what keeps two schedules apart: two lists with the same name share one memory, so each would tell the other's companies that everything changed. Leave it empty only if you run a single list.

## `alertOnChangeOnly` (type: `boolean`):

Turn this on and a quiet company is left out of the results. The first run for a company is always returned, so you can see what got recorded. This hides rows, it does not make the run cheaper: a quiet company costs the same to check as a busy one.

## `checkGoogleAds` (type: `boolean`):

Reads Google's own Ads Transparency Center for this company. On by default.

## `checkLinkedinAds` (type: `boolean`):

Reads the LinkedIn Ad Library for this company. On by default. LinkedIn matches by brand name, so filling in the company names above helps.

## `checkMetaAds` (type: `boolean`):

Reads Meta's Ad Library API. Needs your own access token below. Without one this stays empty and the other platforms are unaffected.

## `metaAccessToken` (type: `string`):

Optional. Meta's Ad Library API only answers to a caller's own token, so bring yours if you want the Meta column filled. It is stored encrypted, never written into your results, and stripped out of every message this actor writes. Outside the EU and UK, Meta's official API only covers political and issue ads.

## `newsLanguage` (type: `string`):

Which Google News edition to search, e.g. en-US, de-DE or fr-FR. Leave it as it is for English.

## `newsCountry` (type: `string`):

Two-letter country for the Google News edition, e.g. US, DE or GB. Leave it as it is for the United States.

## `notifyUrl` (type: `string`):

Optional. Paste a Discord or Slack webhook, a Telegram bot link (https://api.telegram.org/bot<token>/sendMessage?chat\_id=<id>), or any https link of your own, and every company whose signals moved is posted there as it is found. Alerts are free and never change what a run costs. The link is stored encrypted and never written into your results.

## `notifyFormat` (type: `string`):

Leave this on detect and we read the format from the link you pasted. Pick Plain JSON to post a documented JSON body to your own service instead.

## `maxNotificationsPerRun` (type: `integer`):

How many company alerts to send before the rest are folded into one summary message. 0 to 100. Every company is still in your results either way.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `maxConcurrency` (type: `integer`):

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

## `proxyConfiguration` (type: `object`):

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "domains": [
    "notion.com",
    "hubspot.com"
  ],
  "companyNames": [],
  "signals": [
    "hiring",
    "ads",
    "tech",
    "news"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "deltaName": "",
  "alertOnChangeOnly": false,
  "checkGoogleAds": true,
  "checkLinkedinAds": true,
  "checkMetaAds": true,
  "newsLanguage": "en-US",
  "newsCountry": "US",
  "notifyFormat": "",
  "maxNotificationsPerRun": 20,
  "columns": [
    "domain",
    "companyName",
    "openRoles",
    "rolesAddedSinceLast",
    "rolesRemovedSinceLast",
    "hiringGrowthPct",
    "topHiringDepartments",
    "careersUrl",
    "atsName",
    "adsGoogle",
    "adsLinkedin",
    "adsMeta",
    "adsStarted",
    "adsStopped",
    "adsCounts",
    "sampleAdUrls",
    "techStack",
    "techAdded",
    "techRemoved",
    "newsCountSinceLast",
    "latestHeadlines",
    "newsWindowHours",
    "signalScore",
    "changedSignals",
    "firstRun",
    "hiringStatus",
    "adsStatus",
    "techStatus",
    "newsStatus",
    "lastCheckedAt",
    "note",
    "notifyErrors"
  ],
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "notion.com",
        "hubspot.com"
    ],
    "companyNames": [],
    "includeKeywords": [],
    "excludeKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/company-signals-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "domains": [
        "notion.com",
        "hubspot.com",
    ],
    "companyNames": [],
    "includeKeywords": [],
    "excludeKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/company-signals-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "notion.com",
    "hubspot.com"
  ],
  "companyNames": [],
  "includeKeywords": [],
  "excludeKeywords": []
}' |
apify call accountable_eel/company-signals-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/company-signals-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QaXP48tghUHQO2HLJ/builds/RTcSbtFkSpNuVgDAr/openapi.json
