Kairon · Schema

SetSourceBodyDto

B2BSalesArtificial IntelligenceOutreachAutomationMarketing

Properties

Name Type Description
icpId object The ICP every new person must pass before joining the list, from icp_list. Its ACTIVE version is the check, so revising the ICP changes future runs. Omit it or pass null for no ICP: then everyone the
signals array The COMPLETE set of signals this source should carry — at least one. Any signal not listed here is removed. Echo each kept signal with the `id` source_get gave it, or it is treated as new and restarts
status string Whether the source keeps feeding the list. `paused` stops it without losing anything — the signals, their places in their feeds, and every member already found all survive, and resuming carries on whe
contactFilter object Who this list may add, by how much you have already talked to them — the same rule a campaign enrolls by. Omitted leaves the current setting; a new source adds everyone. Narrow it to stop a list filli
dailyTarget integer How many qualified people this list should gain per day (UTC), 1-1000. A floor, not a cap: every event signal still runs in full first, and the lookalike signal then keeps searching until the day's to
peoplePerCompany integer How many people a walk that goes company by company takes at each company, 1-100. Applies to the lookalike (when the ICP describes companies) and to the recently-raised-funds and new-senior-leadership
seatId string Which workspace seat (a channel account id from seat_list) reads this list's SEAT signals: viewed_my_profile, recently_connected and company_followers, and any signal whose own search is measured from
acceptExtraListCharge boolean The workspace's plan includes a number of growing lists (lists whose source is active). Turning a list on past that number costs the plan's price for an extra list, every month, billed to the organiza
View JSON Schema on GitHub

JSON Schema

heykairon-com-set-source-body-dto-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/heykairon-com/json-schema/heykairon-com-set-source-body-dto-schema.json",
  "title": "SetSourceBodyDto",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/heykairon-com-openapi.yml#/components/schemas/SetSourceBodyDto",
  "type": "object",
  "properties": {
    "icpId": {
      "description": "The ICP every new person must pass before joining the list, from icp_list. Its ACTIVE version is the check, so revising the ICP changes future runs. Omit it or pass null for no ICP: then everyone the signals find is added. This is a full replacement, so on a list that HAS an ICP, omitting it removes the check — send back the `icp.id` source_get gave you to keep it. Six signals also SEARCH with the ICP and need one: lookalike, changed_jobs, posted_recently, company_raised_funds, company_leadership_change, company_hiring. Changing the ICP restarts those six from the top of their feed; the others keep their place.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "null"
        }
      ],
      "x-nestjs_zod-uses-3-point-1-syntax": true,
      "x-nestjs_zod-empty-type": true
    },
    "signals": {
      "minItems": 1,
      "type": "array",
      "items": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "changed_jobs",
                "description": "People who recently changed jobs. Needs no Sales Navigator seat of your own: the search runs on Kairon’s Seat Pool. The exception is an ICP whose searched side has a viewer-relative filter (networkDistance, connectionsOf, pastColleague, sharedExperiences…, or a group, account-list or lead-list filter): this signal then reads on the list’s seat, which must have its own Sales Navigator (seatId)."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "posted_recently",
                "description": "People who posted recently. Needs no Sales Navigator seat of your own: the search runs on Kairon’s Seat Pool. The exception is an ICP whose searched side has a viewer-relative filter (networkDistance, connectionsOf, pastColleague, sharedExperiences…, or a group, account-list or lead-list filter): this signal then reads on the list’s seat, which must have its own Sales Navigator (seatId)."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "viewed_my_profile",
                "description": "People who viewed the seat’s profile. Needs a paid seat."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "recently_connected",
                "description": "People who recently accepted a connection. Any seat."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "company_raised_funds",
                "description": "Buyers at companies that recently raised funding. Needs no Sales Navigator seat of your own: the search runs on Kairon’s Seat Pool. The exception is an ICP whose searched side has a viewer-relative filter (networkDistance, connectionsOf, pastColleague, sharedExperiences…, or a group, account-list or lead-list filter): this signal then reads on the list’s seat, which must have its own Sales Navigator (seatId). Takes no config — both hops read the targeted ICP."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "company_leadership_change",
                "description": "Buyers at companies with a recent leadership change. Needs no Sales Navigator seat of your own: the search runs on Kairon’s Seat Pool. The exception is an ICP whose searched side has a viewer-relative filter (networkDistance, connectionsOf, pastColleague, sharedExperiences…, or a group, account-list or lead-list filter): this signal then reads on the list’s seat, which must have its own Sales Navigator (seatId). Takes no config — both hops read the targeted ICP."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "lookalike",
                "description": "People matching the targeted ICP, a few every day, with no event required — the signal to add when a list must keep growing while the event signals are quiet. Needs an ICP with Sales Navigator criteria on at least one side (an ICP with none is refused). Needs no Sales Navigator seat of your own: the search runs on Kairon’s Seat Pool. The exception is an ICP whose searched side has a viewer-relative filter (networkDistance, connectionsOf, pastColleague, sharedExperiences…, or a group, account-list or lead-list filter): this signal then reads on the list’s seat, which must have its own Sales Navigator (seatId). Takes no config — it walks the ICP’s own search. Unlike the event signals it carries no \"why now\", so a lead it appends gives the message writer less to open on."
              },
              "config": {
                "description": "No configuration — this signal takes none.",
                "type": "object",
                "properties": {}
              }
            },
            "required": [
              "signalKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "posted_with_keyword",
                "description": "People who published a post matching a query. Any seat. May appear MORE THAN ONCE on a source — one per query."
              },
              "config": {
                "type": "object",
                "properties": {
                  "keyword": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The boolean search query the posts search runs, e.g. \"hiring SDR\" OR \"sales lead\"."
                  }
                },
                "required": [
                  "keyword"
                ],
                "description": "The query this signal watches for."
              }
            },
            "required": [
              "signalKey",
              "config"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "engaged_with_keyword",
                "description": "People who ENGAGED with posts matching a query — the engagers, not the authors. Any seat. May appear more than once."
              },
              "config": {
                "type": "object",
                "properties": {
                  "keyword": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The boolean search query the posts search runs, e.g. \"hiring SDR\" OR \"sales lead\"."
                  }
                },
                "required": [
                  "keyword"
                ],
                "description": "The query this signal watches for."
              }
            },
            "required": [
              "signalKey",
              "config"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "engaged_with_profile",
                "description": "People who engaged with a chosen profile’s posts. Any seat. May appear more than once — one per watched profile."
              },
              "config": {
                "type": "object",
                "properties": {
                  "target": {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": [
                          "person",
                          "company"
                        ],
                        "description": "Whether the watched profile is a person or a company."
                      },
                      "url": {
                        "type": "string",
                        "minLength": 1,
                        "description": "The LinkedIn URL of the profile whose engagers this surfaces."
                      }
                    },
                    "required": [
                      "kind",
                      "url"
                    ],
                    "description": "The profile being watched."
                  }
                },
                "required": [
                  "target"
                ],
                "description": "Whose engagement this signal surfaces."
              }
            },
            "required": [
              "signalKey",
              "config"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "engaged_with_post",
                "description": "People who commented on or reacted to ONE named post. Any seat. May appear more than once — one per watched post. Short-lived by nature: a post stops gathering engagement after a few days, and this signal then goes quiet on its own."
              },
              "config": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The LinkedIn permalink of the post whose engagers this surfaces."
                  }
                },
                "required": [
                  "url"
                ],
                "description": "The post this signal watches."
              }
            },
            "required": [
              "signalKey",
              "config"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "company_followers",
                "description": "People who FOLLOW a company page the source’s seat administers — an opted-in audience. Walks the whole follower list once, a few pages a day, then keeps picking up new followers. Any seat, but only for a page that seat runs. May appear more than once — one per page."
              },
              "config": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "description": "The LinkedIn company page link (https://www.linkedin.com/company/<slug>). It must be a page the source’s seat ADMINISTERS — LinkedIn shows followers to admins only, and the save is refused otherwise."
                  }
                },
                "required": [
                  "url"
                ],
                "description": "The company page this signal walks."
              }
            },
            "required": [
              "signalKey",
              "config"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "The id of an EXISTING signal, exactly as source_get returned it. Echo it to keep that signal and its place in the feed. Omit it to add a new signal. An id this source does not carry is refused, never treated as new."
              },
              "signalKey": {
                "type": "string",
                "const": "company_hiring",
                "description": "Buyers at companies that just published a job posting matching a search — the hiring signal. The people search at each company uses the ICP’s people criteria. Both searches run on Kairon’s Seat Pool, so no seat of your own is needed — unless the job search sets inYourNetwork, or the ICP’s people side has a viewer-relative filter (that one needs a seat with its own Sales Navigator). Either case reads on the list’s seat (seatId). May appear more than once — one per search (e.g. one per country)."
              },
              "config": {
                "type": "object",
                "properties": {
                  "keywords": {
                    "description": "What the company is hiring FOR — a product, stack or role (\"Oracle\", \"NetSuite\", \"SAP HCM\"), matched anywhere in a posting. A product name usually needs no translation: \"Oracle\" catches Portuguese and Spanish postings alike.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "region": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The ONE country to watch, in plain language (\"Brazil\") or as a LinkedIn geo id. Required: without it LinkedIn silently searches only the seat's own country. Watch another country with another hiring signal."
                  },
                  "datePosted": {
                    "description": "How many days back each run looks. Defaults to 30 days, which is almost always right: LinkedIn removes a posting when the role closes.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 365
                  },
                  "roles": {
                    "description": "Job TITLES from LinkedIn's own taxonomy, in plain language (\"Product Analyst\", \"Head of Growth\"), resolved to title ids. Usually sharper than `keywords`: keywords match anywhere in a posting, while a title matches the ROLE. LinkedIn treats several titles as OR, so pass the variants you mean (\"Product Analyst\", \"Senior Product Analyst\").",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    }
                  },
                  "functions": {
                    "description": "Job FUNCTIONS — the department a role belongs to (\"Product Management\", \"Engineering\", \"Marketing\"), resolved to LinkedIn ids and echoed back. Much wider than `roles`: Product Management alone returned 207 postings where the \"Product Analyst\" title returned 17. Reach for it to size a department across a market; reach for `roles` to find one job.",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    }
                  },
                  "industries": {
                    "description": "The HIRING COMPANY's industry, in plain language (\"Financial Services\", \"Software Development\") — resolved to LinkedIn ids and echoed back. This filters by the employer, not by the role, so it is how a sweep is aimed at the market you actually sell to.",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    }
                  },
                  "seniority": {
                    "description": "LinkedIn's EXPERIENCE LEVEL on the posting. This is the ONLY way to ask for seniority — putting \"Senior\" in `keywords` does the opposite of what it looks like, because LinkedIn ORs the words: the same sweep went from 1241 hits to 2480, wider, not narrower. Several levels are OR (\"senior and above\" is `[\"mid_senior\",\"director\",\"executive\"]`, measured 675 against a 1241 baseline).",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "executive",
                        "director",
                        "mid_senior",
                        "associate",
                        "entry",
                        "intern"
                      ]
                    }
                  },
                  "jobType": {
                    "description": "LinkedIn's JOB TYPE — the employment arrangement. Several are OR.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "full_time",
                        "part_time",
                        "contract",
                        "temporary",
                        "volunteer",
                        "internship",
                        "other"
                      ]
                    }
                  },
                  "presence": {
                    "description": "On-site / hybrid / remote, as the posting declares it. Several are OR.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "on_site",
                        "hybrid",
                        "remote"
                      ]
                    }
                  },
                  "underTenApplicants": {
                    "description": "LinkedIn's UNDER 10 APPLICANTS. The sharpest recency filter there is — it says the posting is not just recent but still UNWORKED, and it cut the same 1241-hit sweep to 127. Use it when the value of the signal is getting there first.",
                    "type": "boolean"
                  },
                  "inYourNetwork": {
                    "description": "LinkedIn's IN YOUR NETWORK — only companies where the seat already has a connection. Warm ground: it cut the same sweep from 1241 to 265, and every hit comes with a path in.",
                    "type": "boolean"
                  },
                  "easyApply": {
                    "description": "LinkedIn's EASY APPLY.",
                    "type": "boolean"
                  },
                  "hasVerifications": {
                    "description": "LinkedIn's HAS VERIFICATIONS — the poster verified their identity.",
                    "type": "boolean"
                  },
                  "fairChanceEmployer": {
                    "description": "LinkedIn's FAIR CHANCE EMPLOYER.",
                    "type": "boolean"
                  },
                  "benefits": {
                    "description": "LinkedIn's BENEFITS, as the posting declares them. Several are OR.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "medical_insurance",
                        "vision_insurance",
                        "dental_insurance",
                        "disability_insurance",
                        "401(k)",
                        "pension_plan",
                        "paid_maternity_leave",
                        "paid_paternity_leave",
                        "commuter_benefits",
                        "student_loan_assistance",
                        "tuition_assistance"
                      ]
                    }
                  },
                  "commitments": {
                    "description": "LinkedIn's COMMITMENTS, as the company declares them. Several are OR.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "career_growth_and_learning",
                        "diversity_equity_and_inclusion",
                        "environmental_sustainability",
                        "social_impact",
                        "work_life_balance"
                      ]
                    }
                  },
                  "minimumSalary": {
                    "description": "LinkedIn's SALARY floor. Both fields are required together, and `value` is in THOUSANDS from a fixed ladder LinkedIn will not interpolate — dollars (USD/AUD/CAD) step 40…200, pounds (GBP) step 20…100. Off-ladder numbers are refused rather than rounded.",
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "type": "string",
                            "enum": [
                              "USD",
                              "AUD",
                              "CAD"
                            ],
                            "description": "A dollar currency — these three share one ladder (40…200, in 20s)."
                          },
                          "value": {
                            "anyOf": [
                              {
                                "type": "number",
                                "const": 40
                              },
                              {
                                "type": "number",
                                "const": 60
                              },
                              {
                                "type": "number",
                                "const": 80
                              },
                              {
                                "type": "number",
                                "const": 100
                              },
                              {
                                "type": "number",
                                "const": 120
                              },
                              {
                                "type": "number",
                                "const": 140
                              },
                              {
                                "type": "number",
                                "const": 160
                              },
                              {
                                "type": "number",
                                "const": 180
                              },
                              {
                                "type": "number",
                                "const": 200
                              }
                            ],
                            "description": "In THOUSANDS of dollars, from LinkedIn's fixed ladder (40 = \"$40,000+\")."
                          }
                        },
                        "required": [
                          "currency",
                          "value"
                        ]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "currency": {
                            "type": "string",
                            "const": "GBP",
                            "description": "Pounds — a different ladder (20…100, in 10s)."
                          },
                          "value": {
                            "anyOf": [
                              {
                                "type": "number",
                                "const": 20
                              },
                              {
                                "type": "number",
                                "const": 30
                              },
                              {
                                "type": "number",
                                "const": 40
                              },
                              {
                                "type": "number",
                                "const": 50
                              },
                              {
                                "type": "number",
                                "const": 60
                              },
                              {
                                "type": "number",
                                "const": 70
                              },
                              {
                                "type": "number",
                                "const": 80
                              },
                              {
                                "type": "number",
                                "const": 90
                              },
                              {
                                "type": "number",
                                "const": 100
                              }
                            ],
                            "description": "In THOUSANDS of pounds, from LinkedIn's fixed ladder (20 = \"£20,000+\")."
                          }
                        },
                        "required": [
                          "currency",
                          "value"
                        ]
                      }
                    ]
                  }
                },
                "required": [
                  "region"
                ],
                "additionalProperties": false,
                "description": "The job search to watch: every job_search market-sweep filter. `region` (one country, plain language) is REQUIRED, and so is at least one of `roles`, `keywords`, `functions`, `industries` — `roles` (job titles) is the sharpest. LinkedIn has no language filter: ask for Spanish-speaking roles with `keywords` such as \"español\". Checked with one job search when saved: a region or term that matches nothing on LinkedIn is refused."
              }
            },
            "required": [
  

# --- truncated at 32 KB (40 KB total) ---
# Full source: https://artifacts.apis.io/heykairon-com/json-schema/heykairon-com-set-source-body-dto-schema.json

Work with this as data

Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for schemas

4 MCP tools reach this
  • find_json_schemasBrowse and filter every JSON Schema in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/heykairon-com-set-source-body-dto"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.