Skip to main content
CornectAPI Docsv1
Sign inGet an API tokenGet started free

Monitors

A monitor watches companies for new signals. Every morning at 09:00 UTC it checks each of its companies for each signal type it watches, and delivers what is new: by email (a daily digest to the workspace owner) or to your webhook. Everything it delivered stays readable in Signals.

Signal types: job_openings (hiring), financing_events (funding rounds), news_events (news) and connections (partnerships).

Cost#

Each company × signal type checked costs 1 credit per daily run, so a monitor watching 5 companies for hiring and funding costs 10 credits a day, every day, until you pause or delete it. A check that could not be made is refunded. A monitor's estimated_daily_cost is that number. If the workspace runs out of credits, its monitors pause themselves (paused_no_credits) and resume at the next run after you top up. A workspace can have up to 10 active monitors.

Who can do what#

Any token can read monitors and their runs (read). Creating, changing, pausing or deleting one, or changing its companies, needs a read_write token and its holder must be an owner or admin of the workspace, checked on every request: a token never outranks the person who made it.

Create a monitor#

POST/api/v1/monitors
FieldTypeRequiredDescription
namestringYesYour name for the monitor.
signal_typesenum[]YesWhat to watch for, one or more of: job_openings (hiring), funding rounds, news, and connections (partnerships).
delivery_methodenumNoHow matched signals reach you. 'email' (default) sends a digest to the workspace owner once per run — no setup required. 'webhook' POSTs each match to an HTTPS endpoint you operate and requires webhook_id; that is the developer path. One of: email, webhook.
webhook_idstringNoRequired when delivery_method='webhook'. Must be omitted for 'email': a monitor cannot carry a webhook it will never use.
domainsstring[]NoThe companies to watch, by domain, e.g. acme.com. At least one.
job_opening_filtersJobOpeningFiltersNoNarrow hiring signals to some roles. Ignored unless job_openings is watched.
slack_connection_idstringNoAlso post each run's signals to this Slack channel. Channels are connected in the app; a monitor's slack_connection_id shows one.

job_opening_filters narrows hiring signals to some roles:

FieldTypeRequiredDescription
title_keywordstringNoOnly openings whose job title contains this text, e.g. sales.
senioritystring[]NoOnly these seniority levels: founder, c_level, partner, president, vice_president, head, director, manager, mid_senior, junior.
categoriesstring[]NoOnly these job categories, e.g. sales, marketing, engineering.
curl -X POST https://api.cornect.io/api/v1/monitors \
  -H "Authorization: Bearer cornect_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"name":"Competitors hiring sales","signal_types":["job_openings","financing_events"],"domains":["acme.com","globex.com"],"job_opening_filters":{"title_keyword":"sales"}}'

The response is the monitor (below), with status 201. This one costs 4 credits a day: 2 companies × 2 signal types.

List and get monitors#

GET/api/v1/monitors
GET/api/v1/monitors/{monitor_id}

List returns { items, total }; Get returns one monitor with its companies and its last 7 runs.

json
{
  "id": "3f1c2a9e-8b7d-4c6e-9a1b-2d3e4f5a6b7c",
  "name": "Competitors hiring sales",
  "signal_types": ["job_openings", "financing_events"],
  "delivery_method": "email",
  "webhook_id": null,
  "job_opening_filters": { "title_keyword": "sales", "seniority": [], "categories": [] },
  "status": "active",
  "last_run_at": "2026-10-11T09:00:34Z",
  "last_run_status": "success",
  "last_error": null,
  "domains": [
    { "domain": "acme.com", "added_at": "2026-10-10T14:02:11Z" },
    { "domain": "globex.com", "added_at": "2026-10-10T14:02:11Z" }
  ],
  "estimated_daily_cost": 4,
  "recent_runs": [],
  "created_at": "2026-10-10T14:02:11Z",
  "updated_at": "2026-10-10T14:02:11Z"
}
FieldTypeDescription
idstringThe monitor's id (monitor_id in paths).
workspace_idstring
created_bystringThe user who created it.
namestring
signal_typesstring[]What it watches for.
delivery_methodstringemail (a daily digest to the workspace owner) or webhook.
webhook_idstringThe webhook it delivers to; null for email.
job_opening_filtersJobOpeningFiltersRole filters for hiring signals, if any.
list_idstringSet when the monitor watches a list from the app: its companies are the list's, and are changed there.
list_namestringThat list's name.
slack_connection_idstringThe Slack channel it also posts to, if any.
slack_channelstringThat channel's name.
statusstringactive, paused_by_user, or paused_no_credits (the workspace ran out of credits; it resumes by itself once there are credits again).
last_run_atstring
last_run_statusstringHow its last run ended, as in a run's status.
last_errorstringWhy it last stopped, if it did.
domainsSignalCronJobDomainResponse[]The companies it watches.
estimated_daily_costintegerCredits each daily run costs: companies × signal types.
recent_runsSignalCronRunSummary[]Its last 7 runs, newest first.
created_atstring
updated_atstring

Update, pause and resume#

PATCH/api/v1/monitors/{monitor_id}

Send only the fields to change. Pause with {"status": "paused_by_user"} (no runs, no charges); resume with {"status": "active"}. A monitor paused for lack of credits cannot be resumed by hand: it resumes at the next run after a top-up.

FieldTypeRequiredDescription
namestringNoA new name.
signal_typesenum[]NoThe full new list of what to watch for (it replaces the old one).
webhook_idstringNoDeliver to this webhook instead.
delivery_methodenumNoSwitch delivery. Moving to webhook needs webhook_id in the same request. One of: email, webhook.
statusenumNopaused_by_user pauses the monitor (no runs, no charges); active resumes it. One of: active, paused_by_user.
job_opening_filtersJobOpeningFiltersNoNew role filters for hiring signals. Send {} to clear them.
slack_connection_idstringNoPost to this Slack channel too. null stops posting to Slack; leave it out to keep it as is.
bash
curl -X PATCH https://api.cornect.io/api/v1/monitors/3f1c2a9e-8b7d-4c6e-9a1b-2d3e4f5a6b7c \
  -H "Authorization: Bearer cornect_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"status": "paused_by_user"}'

Add and remove companies#

POST/api/v1/monitors/{monitor_id}/domains
DELETE/api/v1/monitors/{monitor_id}/domains/{domain}

Add one company per call, with body {"domain": "initech.com"}; its first check is at the next morning run, and the daily cost rises by 1 credit per signal type. Removing answers 204. A monitor that watches a list from the app takes its companies from that list, so both are refused with DOMAINS_FOLLOW_LIST.

bash
curl -X POST https://api.cornect.io/api/v1/monitors/3f1c2a9e-8b7d-4c6e-9a1b-2d3e4f5a6b7c/domains \
  -H "Authorization: Bearer cornect_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"domain": "initech.com"}'

curl -X DELETE https://api.cornect.io/api/v1/monitors/3f1c2a9e-8b7d-4c6e-9a1b-2d3e4f5a6b7c/domains/initech.com \
  -H "Authorization: Bearer cornect_your_token_here"

Delete a monitor#

DELETE/api/v1/monitors/{monitor_id}

Deletes the monitor and its run history, and answers 204. Signals it already delivered stay in Signals. To stop the charges for a while instead, pause it.

Runs#

GET/api/v1/monitors/{monitor_id}/runs
GET/api/v1/monitors/{monitor_id}/runs/{run_id}

A monitor's daily runs, newest first (limit 1–200, offset; the response carries has_more), and one run check by check: each company and signal type, what it found, any error, and whether its credit was refunded.

FieldTypeDescription
idstring
run_datestringThe UTC day of the run.
statusstringrunning, success, partial (some checks failed or credits ran out) or failed.
started_atstring
completed_atstring
domains_totalintegerChecks to make: companies × signal types.
domains_processedintegerChecks made.
domains_skipped_creditsintegerChecks skipped because the workspace ran out of credits.
domains_failedintegerChecks that could not be made (each one refunded).
credits_chargedintegerCredits charged: 1 per check.
credits_refundedintegerCredits refunded for checks that could not be made.
new_items_totalintegerNew signals delivered.

Each check in a run's run_domains:

FieldTypeDescription
domainstringThe company.
signal_typestringWhat was checked for.
statusstringsuccess, skipped_credits, or an error (error_pl, error_other).
error_codestringWhy the check could not be made, if it could not.
items_fetchedintegerSignals found for the company.
items_newintegerOf those, how many were new to this monitor.
items_pushedintegerNew signals delivered.
credit_chargedboolean
credit_refundedboolean
started_atstring
completed_atstring

Errors#

CodeStatusWhen
INSUFFICIENT_SCOPE403A read token tried to change a monitor.
WORKSPACE_EDIT_FORBIDDEN403The token's holder is not an owner or admin. A new token will not help.
NOT_FOUND404No such monitor (or run) in your workspace.
WORKSPACE_CRON_JOB_LIMIT409The workspace already has 10 active monitors.
DOMAIN_ALREADY_ACTIVE409The monitor already watches that company.
DOMAINS_FOLLOW_LIST409The monitor watches a list; change its companies in the list.
STATUS_TRANSITION_FORBIDDEN409Resuming a monitor paused for lack of credits.
WEBHOOK_REQUIRED422Webhook delivery without a webhook_id.
WEBHOOK_NOT_FOUND422That webhook is not in your workspace.
—422Any other invalid field: the message names it.
—429Rate limit exceeded (120/min to read, 60/min to change).
Webhooks and Slack are set up in the app

A monitor can deliver to a webhook, and also post to a Slack channel, that you set up in the Cornect app; pass its id here. A monitor shows the ids it uses.