Who Is Already In The Pipeline (pre-import check)
li_check_targetsRead-only: who among these profile URLs has ALREADY been approached from the accounts you can see. It writes nothing, queues nothing and BLOCKS nothing — a collision is information, not an error, and importing one is allowed.
WHEN NOT TO CALL IT: not before an import. li_ingest_prospects and li_create_campaign run this very check themselves, just before they write, and hand the report straight back as collisions — so calling this first does the same work twice and returns the same answer twice. For li_ingest_prospects theirs is also the BETTER answer: it knows which campaign the batch is landing in, so people already in it read as in_this_campaign, an idempotent update that costs nothing, while a call made out here without a campaignId files those same people as a clash somewhere else. (li_create_campaign CREATES the campaign, so there is nothing to be already in — its report is the same one you would get here, minus the extra call.) Reach for this when you have NOT decided to import — triaging a list somebody just sent you, deciding whether a batch is worth paying to research before you spend lookups on it, or answering "do we already know these people" as a question of its own.
Why it matters: re-importing someone into the SAME campaign is idempotent (their note and unsent step text are refreshed, nothing new is queued). Importing them into a DIFFERENT campaign creates a second invite the drip will attempt, and what happens is decided at send time — LinkedIn showing a pending invite yields "already invited" and someone already 1st-degree yields "already connected", neither of which sends anything, but BOTH still spend a ~50s browser session that this account then has to wait behind. Anything else sends a REAL second invite, charged against each account's rolling 7-day invite allowance this system enforces, set by the account's detected LinkedIn tier — 63-70 a week (5-10 a day) new or unverified, 90-100 a week (18-24 a day) established, 135-150 a week (25-30 a day) Premium, redrawn within the range each week. Our own policy, not a published LinkedIn limit; the daily band exists only to stop a burst. li_list_accounts gives each account's actual numbers.
Each person lands in exactly one bucket, most advanced first: in_this_campaign (benign — an idempotent update), messaged_elsewhere, connected_elsewhere, invited_elsewhere, unreachable_elsewhere (a PERMANENT invite failure is on record, so retrying spends a session for nothing), closed_elsewhere, and queued_elsewhere (another campaign has them queued and has NOT invited them yet — the only collision still cheap to avoid, since both campaigns will now invite them and the second is a duplicate out of the same daily budget). collisions names each one with its campaign and account, counts totals the buckets, fresh is how many none of your accounts has touched, and summary is one true sentence safe to relay verbatim.
THE BUCKET IS ONLY THE HEADLINE. A person can be in several campaigns on several accounts: otherCampaigns counts the rest per person, and view: "people" lists EVERY membership of every person (campaign, account, campaign status, connection, message, outcome, inbound) as one compact table — up to 1000 URLs in one call, so it is also the way to ask which of a list are in which campaigns. Building several new campaigns at once? Pass campaignNamePrefix (or campaignId): anyone already in one of them is named in batch.members whatever their bucket says.
Set groupByCompany: true to also group these people by employer and say which firms you already have a contact at. Read a warm firm BOTH ways: somebody there already knows you, or the same note is about to land twice inside one company. Only you can tell which, so this reports it and holds nothing. Employers come from profiles already looked up plus your own contact rows, so unknownCompany means "not matched", never "no employer".
The report is BOUNDED BY WHAT YOU CAN SEE: it covers your own accounts and reports nothing at all — no name, no count, no bucket — about anything outside them, so read a clean result as "not in your pipeline" rather than "nobody has ever approached them". scopeNote says the same in the reply. Pass campaignId when you already know the campaign you are importing into; without it, people who are already IN that campaign are reported as collisions elsewhere, which overstates the cost.
The reply is GROUPED by default (view: "summary"): the explanation is said ONCE per bucket instead of once per person, each campaign is described once in sites instead of on every row, and every person named keeps their URL, their name and a site index pointing at their own campaign and account — measured at 56% smaller on a batch with sixty collisions, and the saving grows with the batch. ⚠️ IT IS CAPPED, so read peopleHidden: a bucket names at most 50 people and states how many it did not, while count stays the true bucket size — sixty in one bucket gives you fifty names and peopleHidden: 10, and those ten are NOT fresh. view: "full" names every one of them, in the order you submitted them, each carrying its own copy of the sentence.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| view | No | How much to return. "summary" (the default) groups the colliding people by bucket and lists each campaign once in `sites`, naming up to 50 people per bucket (`peopleHidden` counts the rest) and `otherCampaigns` per person. "people" is EVERY campaign each person is in, one table row per person per campaign (account, campaign status, connection, message, outcome, inbound), uncapped and compact — for "which of these URLs are in which campaigns". "full" returns flat rows with every sentence, plus `people` with whole membership objects. | |
| fields | No | view "people" only: which columns besides profile and campaign, from name, bucket, connection, message, outcome, inbound. Default all. | |
| format | No | view "people" only: "json" (default) returns `rows` as arrays matching `columns`; "csv" returns the same table as `csv` text. | |
| sessionId | No | Account you intend to import from (id) | |
| campaignId | No | The campaign you are importing INTO, when it already exists. People already in it are then reported as `in_this_campaign` (an idempotent update) instead of as a collision elsewhere. | |
| profileUrls | Yes | LinkedIn profile URLs to check, max 1000 per call. A longer list is REFUSED rather than silently trimmed — split it and call again. | |
| sessionLabel | No | Account you intend to import from, e.g. "Deven". Validated only — naming it does NOT narrow the check, because a collision on another of your accounts is still a collision and hiding it would defeat the point. | |
| groupByCompany | No | Also group these people by employer and name the firms you already have a contact at. Off by default because it costs extra queries. Nothing is held either way. | |
| campaignNamePrefix | No | The campaigns you are BUILDING, by name prefix (case-insensitive), e.g. "PR test Oct". Anyone already in one of them is listed in `batch.members` (never capped) and marked `inBatch`, whatever their bucket says. Use it when splitting a list across several new campaigns. |