Skip to content
Signal
Dashboard

Monitors

The monitor object: config types, frequency, status and the webhook URL.

A monitor looks for signals on a schedule. The V2 API creates organization-owned monitors through POST /monitors or the compatible campaign-nested route. Its config says what to watch and which signal types to look for. Each scheduled run of a monitor is a run of kind monitor, and the run can create signals. To move a V1 integration, read Migrate from V1.

A source campaign is required only for signal-sheet. A topic monitor needs no source campaign or existing records. Monitor targets and signal subjects explains independent monitors and retained signals in this candidate.

The monitor object

FieldTypeDescription
idUUIDRequired. ID of the monitor.
campaign_idUUIDNullable. ID of the campaign of the monitor. Null for an independent monitor.
namestringRequired. Name of the monitor, 1 to 200 characters.
configobjectNullable. What the monitor looks for. See Config types. Null for an older monitor whose config the V2 API cannot read.
frequencyenumNullable. daily, weekly or monthly. Null when the frequency is not known.
statusenumRequired. active or paused.
next_run_attimestampNullable. Time of the next scheduled run. Null when the monitor is paused.
{
  "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
  "campaign_id": "3f2b8a4e-1c5d-4e7f-9a0b-6c2d8e1f4a7b",
  "name": "Funding rounds",
  "config": {
    "type": "signal-topic",
    "signal_types": [
      {
        "type": "funding",
        "display": "Funding",
        "description": "Investment rounds and capital raises"
      }
    ],
    "entity_type": "company",
    "webhook_url": null,
    "topic_criteria": "Data integration companies that raise a Series A",
    "geographic_filters": null,
    "industry_filters": null,
    "company_size_filters": null
  },
  "frequency": "weekly",
  "status": "active",
  "next_run_at": "2026-09-30T12:00:00.000Z"
}

Config types

config.type selects what the monitor watches. The type cannot change after create.

TypeWatchesFields of the type
signal-topicA topic. It needs no records.topic_criteria (required): the topic in natural language. geographic_filters, industry_filters, company_size_filters: nullable arrays of strings. Null means all.
signal-sheetThe accounts or people of a campaign.source_campaign_id (required): the campaign to watch. It can be the campaign of the monitor. Its account type must match entity_type; watching people needs entity_type: person and a campaign that targets people. An empty source is valid when it supports the requested record type. entity_filters (nullable): conditions on the records.
signal-csvThe companies or people of an uploaded CSV file.file_id (required): ID of the file, 24 hexadecimal characters. primary_column: the column with the record names. Default name.

The V2 API cannot create the file_id of a signal-csv monitor. To watch the records of a CSV file, import the file with upload_import, then create a signal-sheet monitor for the campaign.

Every config type also has these fields:

FieldTypeDescription
typeenumRequired. signal-topic, signal-sheet or signal-csv.
signal_typesarrayRequired. The signal types to look for. Each item has type (a signal type), display (a display name) and description (the events to find). Use other for a custom type.
entity_typeenumThe type of the monitored records: company, person, school_district, job_board or product. Default company.
webhook_urlstringNullable. See Webhook URL.

entity_filters limits the records that a signal-sheet monitor watches. Null watches every record.

  • Each key is status or the path of a data field, for example data.industry.value. status matches the stored review state. A record with no stored state reads new. To match new records, send {"status": {"$in": ["new", null]}}. Older records can store contacted, which the V2 API shows as reviewed. To match every record that reads reviewed, send {"status": {"$in": ["reviewed", "contacted"]}}.
  • Each value is a JSON scalar, which the field must equal, or an object of operators.
  • $eq, $ne, $gt, $gte, $lt and $lte take a scalar.
  • $in and $nin take a list of scalars.
  • $exists takes true or false.
  • $regex takes a pattern of at most 200 characters. Start the pattern with (?i) to ignore case.
  • Other fields, other operators and top-level operators such as $or or $where give 422.

Frequency and status

FieldValuesRule
frequencydaily, weekly, monthlyDefault weekly. The schedule starts from the time of the create_monitor call. A new frequency starts a new schedule cycle from the time of the update_monitor call. A monthly schedule made on day 29, 30 or 31 skips the months that do not have that day. Read next_run_at.
statusactive, pausedDefault active. active lets the schedule start runs. paused starts no run. A monitor without a schedule is paused.
  • When the monitor is active, the first run starts at next_run_at. A paused monitor has a null next_run_at. create_monitor does not start a run at once. run_monitor starts one run now. The schedule does not change.
  • Each run of a monitor has kind monitor and the monitor_id of the monitor. result.completed is the number of signals that the run processed. Read Runs.
  • A scheduled run needs credits. A run that cannot start for lack of credits gets the status skipped.
  • Send status paused to stop the scheduled runs. Send active to start them again.

Webhook URL

config.webhook_url is a URL that gets a notification when a run of the monitor ends. config.format selects the payload: legacy (the default) or v2. This section describes the legacy format. V2 webhooks describes the signed v2 format and its verification secret. There is no event subscription. Discovery, import and export runs have no webhook setting in the V2 API.

BehaviorValue
MethodPOST with a JSON body.
BodyAn object with event_type, timestamp (UTC) and data. event_type is, for example, run.signal.completed, run.signal.failed, run.signal.cancelled or run.signal.crashed. The V2 API reference does not define the fields of data.
URL rulesThe URL must use HTTPS. Signal does not send to localhost, 127.0.0.1 or ::1. The API accepts any string. Signal sends no notification to a URL that breaks these rules.
Timeout30 seconds for each attempt.
RetriesUp to 5 retries after a 5xx response, a timeout or a connection error. The delays are 2, 4, 8, 16 and 32 seconds. A 4xx response gets no retry.
SignatureNone. A legacy request has no signature header.
FailureA failed notification does not change the run.

Signal routes a notification to the currently configured webhook of the monitor that started the run. Signal skips delivery when it cannot confirm that monitor. Notification payload IDs are not guaranteed to be V2 IDs.

Treat the notification as a prompt to read data through the API. Call get_run or list_runs for the run status. To read the new signals of a run, call list_signals with the monitor_id of the run and created_after set to the started_at of the run.

To set or clear the URL, send config.webhook_url to update_monitor. Send null to clear it.

Roles and changes

Monitor operations use resource permissions. Organization roles do not replace them. See Permissions.

  • Reading needs monitor.read. Listing monitors through a campaign also needs campaign.read.

  • Creation needs monitor.write and schedule.write. An active schedule also needs run.write. Campaign-linked creation needs campaign access, and each source needs its own reads.

  • Updating needs monitor.write. Changing frequency or status also needs schedule.write, plus campaign.write for a campaign-linked monitor. Enabling recurring execution needs run.write.

  • Setting or clearing the webhook URL needs webhook.write.

  • run_monitor needs monitor.read, run.write, and the permissions of its execution inputs and effects.

  • Deletion needs monitor.write and schedule.write. Canceling queued or running work also needs run.write.

  • update_monitor changes only the fields in the body. A config change must use fields of the current config type.

  • update_monitor gives 409 when you send config for a monitor with a null config. It also gives 409 when you send status active for a monitor with a null campaign_id and no schedule.

  • delete_monitor deletes the monitor, its schedule and the signals that it found. It cancels the active runs of the monitor. After the delete, get_run and list_runs do not find the runs of the monitor. You cannot undo the delete.

Operations

Each path below follows $LINKT_API_URL/v2. Set LINKT_API_URL to the origin only, for example https://api.signal.linkt.ai.

OperationMethod and pathPurpose
list_monitorsGET /campaigns/{campaign_id}/monitorsList the monitors of a campaign.
create_organization_monitorPOST /monitorsCreate a monitor without campaign provenance. Returns 201.
create_monitorPOST /campaigns/{campaign_id}/monitorsCreate a monitor. Returns 201.
get_monitorGET /monitors/{monitor_id}Get one monitor.
update_monitorPATCH /monitors/{monitor_id}Change the name, config, frequency or status.
delete_monitorDELETE /monitors/{monitor_id}Delete a monitor and its signals. Returns 204.
run_monitorPOST /monitors/{monitor_id}/runsStart one run of the monitor now. Returns 202. Uses credits.

The next example creates a paused monitor. A paused monitor starts no run and uses no credits. Send status active to start the schedule. Each scheduled run uses credits.

curl --fail-with-body --request POST "$LINKT_API_URL/v2/campaigns/$CAMPAIGN_ID/monitors" \
  --header "x-api-key: $LINKT_API_KEY" \
  --header "Content-Type: application/json" \
  --data "$(jq -cn --arg CAMPAIGN_ID "$CAMPAIGN_ID" '{"config":{"signal_types":[{"description":"A new funding round or a new investment.","display":"Funding","type":"funding"},{"description":"A new executive in data, IT, or engineering.","display":"Leadership change","type":"leadership_change"}],"source_campaign_id":"0190a4e2-0000-7000-8000-000000000001","type":"signal-sheet"},"frequency":"weekly","name":"Funding and leadership changes","status":"paused"} | walk(if . == "0190a4e2-0000-7000-8000-000000000001" then $CAMPAIGN_ID else . end)')"

API reference: create_monitor

curl --fail-with-body --request GET "$LINKT_API_URL/v2/campaigns/$CAMPAIGN_ID/monitors?limit=5" \
  --header "x-api-key: $LINKT_API_KEY"

API reference: list_monitors

Monitor create and update reject unknown fields inside each signal_types item with 422 validation_error. Each item accepts type, display and description. The validation details identify the unknown field with extra_forbidden.

On this page