---
title: "Update signal"
method: PATCH
path: "/api/v1/signals/{signal_id}"
tags: ["Account Management"]
---

# Update signal

`PATCH /api/v1/signals/{signal_id}`

## Request

- Base URL: `https://api.rodz.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.rodz.io/api/v1/signals/{signal_id}`
- Auth: HTTP bearer

Pause or resume a signal, change its filters, its webhook endpoint or its daily lead limit — without recreating it or losing its lead history.

**Input:** `name` (new signal display name), `webhookUrl` (new endpoint URL where leads are delivered), `config`, `dailyLeadLimit` (max leads per day, 1–999,999), `duplicateHandling` (duplicate-lead policy: `refuse` = never re-accept a lead already delivered, `allow` = always accept, or `Xd` = accept again after X days, e.g. `7d`), `status` (active or paused).

`config` **is merged into the stored configuration**: send only the fields you want to change, and every field you omit keeps its current value. To clear a list, send it empty (for example `targetPersonas: []`). A complete object still overwrites every field it carries.

**Watched lists:** on a watchlist, `companies` (or `profiles` on a job-change watchlist) sent in `config` are **added** to the watched list, exactly as `POST /api/v1/watchlists/{signalId}/companies` (or `/profiles`) does in its default `append` mode — nothing is removed, and the list is not echoed back in `config`. To replace the whole list use that endpoint with `mode: replace`; to remove one entry, `DELETE` it. A LinkedIn link in a company list that names no company (a person's profile, a post) is refused with 422 `INVALID_COMPANY_ENTRY`; a Sales Navigator company link is read as the company's LinkedIn id.

**Connection signals:** people added to `linkedinProfileUrls` start being watched, and people removed stop being watched, as on activation.

**Output:** the updated signal with its stored `config`, `applied` and `warnings` (see GET), status, real-time lead metrics (leads today + cumulative total since creation), and timestamps (created, updated, last lead received). When the PATCH carried a watched list, `watchlist` reports how many entries are now watched, were already watched, or were rejected.

## Path parameters

- `signal_id` string, required

## Request body

- object: Update a signal via the public API.
  - `name` string, nullable
  - `webhookUrl` string, nullable
  - `destinations` SignalDestinations: Where a signal's qualified leads are pushed, in addition to ``webhookUrl``. Every provider you name must already be connected on your account — connect the API-key ones via ``PUT /api/v1/integrations/{provider}``, and the OAuth ones (HubSpot, Pipedrive, Google Sheets) once in the dashboard; both are then selectable here. Discover campaign / flow / audience ids (and connected-account ids for multi-account providers like Lemlist) via ``GET /api/v1/integrations`` and ``GET /api/v1/integrations/{provider}/campaigns``.
    - `instantly` InstantlyDestination
      - `campaignId` string, required: Instantly campaign id to push leads into.
    - `lemlist` LemlistDestination
      - `campaignId` string, required: Lemlist campaign id.
      - `integrationId` string, nullable: Which connected Lemlist account to use. Required only if you've connected more than one; discover ids via GET /api/v1/integrations.
    - `smartlead` SmartleadDestination
      - `campaignId` string, required: Smartlead campaign id.
    - `emelia` EmeliaDestination
      - `campaignId` string, required: Emelia campaign id.
      - `campaignType` string, nullable: Emelia campaign type ("email" or "linkedin").
    - `lgm` LgmDestination
      - `audienceName` string, required: LaGrowthMachine audience name.
      - `integrationId` string, nullable: Which connected account (only if more than one).
    - `gong` GongDestination
      - `flowId` string, required: Sales-engagement flow id to assign leads to.
      - `ownerEmail` string, nullable: Flow owner email.
      - `integrationId` string, nullable
    - `hubspot` EnabledDestination
      - `enabled` boolean, required: Turn this destination on or off for the signal.
    - `pipedrive` EnabledDestination
      - `enabled` boolean, required: Turn this destination on or off for the signal.
    - `googleSheets` GoogleSheetsDestination
      - `sheetUrl` string, required: Target Google Sheet URL (must be accessible to your connected Google account).
    - `customWebhook` CustomWebhookDestination
      - `url` string, required: HTTPS endpoint that receives each lead (same payload as webhookUrl).
  - `config` object, nullable: MERGED into the stored configuration: send only the fields you want to change, every field you leave out keeps its current value. To clear a list, send it empty (e.g. `"targetPersonas": []`). A complete object still overwrites every field it carries. On a watchlist, `companies` (or `profiles` on a job-change watchlist) sent here are ADDED to the watched list, exactly as `POST /api/v1/watchlists/{signalId}/companies` in its default `append` mode: nothing is removed, and `watchlist` in the response reports what was taken in. To replace the list or remove an entry, use that endpoint with `mode: replace`, or `DELETE` on the entry.
  - `dailyLeadLimit` integer, nullable
  - `duplicateHandling` string, nullable: Duplicate lead handling: 'refuse' (never accept), 'allow' (always accept), or 'Xd' (accept a duplicate after X days, e.g. '7d'). Optional — defaults to 'allow', so a contact who triggers this signal a second time is delivered a second time.
  - `status` string, nullable: Signal status: active, paused

## Response `200`

Successful Response

- object: Create response for the two watchlist signals. A separate model rather than an optional field on ``PublicSignalResponse``: this spec inlines the response schema at every signal endpoint (36 of them), so carrying the extra object on the shared model documented a phantom ``watchlist`` field on 34 endpoints that never return one — and doubled the size of the published spec to say so.
  - `id` string, required
  - `name` string, required
  - `status` string, required
  - `signalTypeId` string, required
  - `webhookUrl` string, nullable
  - `config` object, nullable: Signal-specific configuration
  - `dailyLeadLimit` integer, required
  - `leadsToday` integer, required
  - `leadsTotal` integer, required
  - `duplicateHandling` string, required: Duplicate lead handling: 'refuse' (never accept), 'allow' (always accept), or 'Xd' (accept after X days)
  - `createdAt` string, required
  - `updatedAt` string, required
  - `lastLeadAt` string, nullable
  - `applied` object: Settings this signal runs with where they differ from `config`, keyed like `config`. `{}` when every stored setting is applied as stored. A `null` value means the stored field is not used by this signal. Every entry is explained by a warning naming the same field.
  - `warnings` SignalConfigWarning[]: What you should know about this configuration: values applied differently from what is stored, and filter values that are probably not what you meant. Computed from the stored configuration, so they appear on GET as well as on create and update - a signal created before these fields existed reports them too. Never an error: the signal is created or updated regardless.
    - `code` string, required: Stable identifier. `VALUE_BELOW_MINIMUM` (a value under the documented minimum is applied as the minimum), `VALUE_ADJUSTED` (a value the search cannot use as written is applied as the nearest one it can, e.g. a `publishedDate` of 14d searches 15 days), `FIELD_NOT_USED` (a stored field this signal ignores), `UNKNOWN_SIZE_NOT_ACCEPTED`, `CATEGORY_WITH_OWN_INDUSTRIES` (a category listed together with industries it already covers), `UNKNOWN_INDUSTRY` (a value matching no published industry), `UNKNOWN_FIELD` (a config key this signal does not have), `UNKNOWN_TOOL` / `UNKNOWN_CATEGORY` (a tracked tool or category name that is not in the catalog of GET /api/v1/signals/technographic-tools; on a GMB Discovery signal, a `category` that is not a Google Maps category, so the signal matches no business), `UNKNOWN_CITY` (GMB Discovery: cities in `cities` that are not in the signal's `country` — `values` lists them; when none is, the signal matches no business until `cities` or `country` is changed; never an error, nothing stored is changed), `NO_FOLLOWER_SOURCE` (a Company Followers signal with no follower extraction set up yet, so it produces nothing), `DAILY_LIMIT_PENDING` (a job signal's `dailyLeadLimit` changed less than a day after its search was last rebuilt: the search keeps its previous volume until the time in `values`, while the leads delivered per day already follow the new limit), `WATCHED_LIST_EMPTY` (a watchlist reading its list from your CRM holds no company or person — the CRM is not connected, the list could not be read, or it is empty — so it produces nothing until the list fills; cleared on its own once it does), `QUOTE_REQUIRED` (an `active` Company Followers signal in `icp` mode whose follower extraction has not been priced and accepted, so it produces nothing yet: `values[0]` says why — `not_requested`, `awaiting_acceptance` (then `values[1]` is the quoted price in credits), `expired`, `declined`, `failed`, or, after an automatic quote, `auto_quote_refused` / `auto_accept_refused` (then `values[1]` is the error code); the message names the call to make — see POST /api/v1/signals/{signal_id}/extraction/quote; cleared once a quote is accepted), `WATCHED_LIST_IMPORTING` (a company watchlist whose HubSpot list is still being read: companies are added as they arrive; `values[0]` is the number of members read so far, `values[1]` the list id; cleared once the whole list is read), `MATCHING_CONFIRMATION_REQUIRED` (a New Decision Maker or Account watchlist whose companies must be matched to their LinkedIn company page before they can be watched, at a cost above the amount we match without asking: nothing is matched or charged until you confirm with POST /api/v1/watchlists/{signalId}/companies/confirm-matching; `values[0]` is the maximum cost, `values[1]` the number of companies to match; cleared once confirmed), `DESTINATION_UNAVAILABLE` (the outreach campaign this signal sends leads to cannot receive them — not found, archived, ended or without any step — so leads are not reaching it: `values[0]` is `campaign_not_found`, `campaign_archived`, `campaign_ended` or `campaign_no_steps`; cleared once a lead reaches the campaign or the signal's destination is changed), `DESTINATION_NEEDS_CONTACT` (the signal delivers companies with no contact and a destination in `destinations` only accepts people, so none of its leads reach that destination), `DESTINATION_SKIPS_COMPANY_ONLY` (some leads are companies with no contact, e.g. no one matching your personas was found, and a destination only accepts people), `DESTINATION_NEEDS_EMAIL` (a destination only accepts leads with an email and `getEmails` is off) — for these three, `values[0]` is the destination key in `destinations`, the next values are the fixes: `add_persona` (turn on `enablePersonaTargeting` with `targetPersonas`), `require_contact` (turn on `requireContact`), `add_company_destination` (add a destination that accepts companies: `hubspot`, `pipedrive`, `googleSheets` or `customWebhook`), `enable_email_finding` (turn on `getEmails`); severity `warning` when those leads reach no destination at all, `info` when another destination still receives them; never blocks the save; `COMPANY_PAGE_UNAVAILABLE` (a Company Followers signal whose extraction stopped because a page in `linkedinCompanyUrls` does not exist on LinkedIn: nothing was extracted or charged; `values` lists the pages; replace them with PATCH /api/v1/signals/{signal_id}, then start the extraction again; cleared once the pages are replaced or a new extraction runs), `COMPANY_PAGE_UNVERIFIED` (create / PATCH responses only: a page in `linkedinCompanyUrls` could not be verified at that moment and was accepted; `values` lists them — if one does not exist, its extraction stops without using credits and the signal carries `COMPANY_PAGE_UNAVAILABLE`).
    - `severity` string, required: `info`: nothing to do. `warning`: probably not what you meant.
    - `field` string, required: The `config` key concerned, camelCase (or `dailyLeadLimit`).
    - `message` string, required
    - `values` string[]: The offending values, when there are some.
  - `watchlist` object, nullable: What the watchlist create actually took in. Returned only for watchlist signals. The rejected/unresolved counts are surfaced rather than swallowed: a watchlist that quietly dropped half its list looks identical to a healthy one until the leads never arrive.
    - `watched` integer, required: Entries now being watched by this signal (people, or companies).
    - `rejected` integer: Entries that could not be used — a LinkedIn URL that is not a personal profile, or a company row with neither a name nor a domain.
    - `alreadyWatched` integer: Entries already on this signal's list, left unchanged.

## Other responses

- `400`: Invalid update: bad status value, or an unrecognized location filter
- `422`: Validation Error
- `429`: Rate limit exceeded. Retry after the number of seconds in the `Retry-After` response header.

---

[API](https://skmtc.dev/rodz/apis/rodz-api.md) · [All operations](https://skmtc.dev/rodz/apis/rodz-api/llms.txt) · [OpenAPI document](https://skmtc.dev/rodz/apis/rodz-api/revisions/3003505ff896?raw)
