> ## Documentation Index
> Fetch the complete documentation index at: https://docs.linkedcamp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Campaigns

> The campaign lifecycle: create, configure, source prospects, launch, and manage once live.

<Info>Requires the **Campaigns** permission. Tools in this group are hidden from `tools/list` and refused on call when your plan does not grant it.</Info>

| Tool | Kind |
| - | - |
| [`campaign_activity_summary`](#campaign_activity_summary) | Read-only |
| [`campaign_add_prospects`](#campaign_add_prospects) | Write, Destructive |
| [`campaign_create`](#campaign_create) | Write |
| [`campaign_create_ab_variant`](#campaign_create_ab_variant) | Write |
| [`campaign_delete`](#campaign_delete) | Write, Destructive |
| [`campaign_duplicate`](#campaign_duplicate) | Write |
| [`campaign_export_stats`](#campaign_export_stats) | Write |
| [`campaign_generate_ai_sequence`](#campaign_generate_ai_sequence) | Write |
| [`campaign_get`](#campaign_get) | Read-only |
| [`campaign_launch`](#campaign_launch) | Write, Destructive |
| [`campaign_list`](#campaign_list) | Read-only |
| [`campaign_logs`](#campaign_logs) | Read-only |
| [`campaign_preview_message`](#campaign_preview_message) | Read-only |
| [`campaign_send_test_email`](#campaign_send_test_email) | Write, Destructive |
| [`campaign_set_source`](#campaign_set_source) | Write, Destructive |
| [`campaign_set_status`](#campaign_set_status) | Write |
| [`campaign_update`](#campaign_update) | Write |
| [`campaign_upload_leads`](#campaign_upload_leads) | Write |
| [`search_url_build`](#search_url_build) | Read-only |

## campaign\_activity\_summary

<Badge color="blue">Read-only</Badge>

Aggregate counts of pending, completed and failed actions across the campaign. Three numbers for the whole campaign — the cheapest "is it working" check. For the same split per step use `sequence_step_stats`, and for the leads behind one step `sequence_leads_at_step`.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

## campaign\_add\_prospects

<Badge color="orange">Write</Badge> <Badge color="red">Destructive</Badge>

<Warning>Marked destructive in the protocol — your MCP client asks for confirmation before running it.</Warning>

Top up an already-running campaign with prospects from a new source, without touching its sequence or existing leads. Runs in the background and can take several minutes. Two hard preconditions, both enforced by the backend as thrown errors: the campaign must be ACTIVE — a DRAFTED one fails with "Campaign is not active!" — and it must have finished filtering its first batch. So this is never how a new campaign gets its audience: for that use `campaign_set_source` (a search URL) or `campaign_upload_leads` (CSV rows) before launching. It also does not add leads to this campaign directly — the backend creates a child campaign pointing at this one, which is why `campaign_delete` reports removing active children.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="type" type="enum (9 values)" required>
  Source kind for the new batch.
</ParamField>

<ParamField path="url" type="string">
  LinkedIn source URL, for non-CRM types.
</ParamField>

<ParamField path="field" type="string">
  CRM sources: contact property holding the profile URL.
</ParamField>

<ParamField path="query" type="string">
  CRM sources: segment / list query.
</ParamField>

## campaign\_create

<Badge color="orange">Write</Badge>

Create a DRAFTED campaign. Nothing sends until `campaign_launch`. Pass `sourceUrl` to set the prospect source at the same time (a LinkedIn or Sales Navigator search URL, a group, an event, or a post). For a CSV-driven campaign, omit `sourceUrl` and follow up with `campaign_upload_leads`. This is the right starting point for EVERY new campaign. Never begin one with `campaign_duplicate` unless the user named a campaign to copy — see that tool for why. It creates the campaign and nothing else: the sequence comes from `flow_set`, accounts and limits from `campaign_update`, and it only sends after `campaign_launch`.

### Parameters

<ParamField path="title" type="string" required>
  Campaign name, shown throughout the app.
</ParamField>

<ParamField path="sourceUrl" type="string">
  LinkedIn search / Sales Navigator / Recruiter / group / event / post URL to harvest prospects from. The source type is inferred from the URL shape.
</ParamField>

## campaign\_create\_ab\_variant

<Badge color="orange">Write</Badge>

Split a campaign into an A/B pair so two versions of the sequence run against comparable halves of the audience. Compare them later with `analytics_campaign`. This SPLITS, it does not copy: the backend moves half of the not-yet-contacted leads out of the original into a new DRAFTED campaign, copies the flow, and renames the original to "\<title> \[A]". The original therefore ends up with half the audience it had. It needs more than 10 leads still waiting to be contacted and refuses otherwise with "Not enough leads to do AB testing, Duplicate campaign instead!" — in which case `campaign_duplicate` is the backend's own suggestion. Use `campaign_duplicate` when the audience should be left alone, and this when the point is to compare two versions on one audience.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

## campaign\_delete

<Badge color="orange">Write</Badge> <Badge color="red">Destructive</Badge>

<Warning>Marked destructive in the protocol — your MCP client asks for confirmation before running it.</Warning>

Remove a campaign from your account by moving it to DELETED. Nothing is erased — the campaign, its leads, sequences and activity records all stay in the database, and the campaign simply stops appearing in listings. There is no tool to bring it back, so confirm with the user first. Sending stops because the workers only pick up ACTIVE campaigns; to stop sending without removing the campaign, that is a pause, which belongs in the web app. The only tool allowed to write a campaign status, and the only value it writes is DELETED — `campaign_update` has no status parameter and nothing sets ACTIVE, PAUSED or ARCHIVED. Deleted campaigns vanish from `campaign_list`, so confirm before calling: there is no undelete.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

## campaign\_duplicate

<Badge color="orange">Write</Badge>

Copy one specific existing campaign — its settings and its whole sequence — into a new DRAFTED campaign, without copying the leads. Use this ONLY when the user asks to duplicate a campaign they have named. It is not a way to start a new campaign: a new campaign has nothing to duplicate, and the copied sequence carries the original audience's messaging. To start fresh, use `campaign_create`. The copied steps cannot be rewritten from here either — `sequence_update` edits are reverted at launch on a campaign that has not launched yet, so a duplicate is only useful when the existing copy is meant to be kept.

### Parameters

<ParamField path="campaignId" type="string" required>
  The existing campaign the user named. Never guess this — get it from `campaign_list`.
</ParamField>

## campaign\_export\_stats

<Badge color="orange">Write</Badge>

Generate a CSV export of campaign performance. Returns a filename; the file is served from the CDN and also emailed to the account owner — so it leaves the conversation, which is worth mentioning before calling it. Performance numbers, not people: for a file of prospects use `lead_export`, and to read the numbers here instead use `analytics_campaign`.

### Parameters

<ParamField path="campaignId" type="string">
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="range" type="object">
  Date window as \{ from, to } — epoch milliseconds or ISO 8601. Omit for the backend default.

  <Expandable title="properties">
    <ParamField path="from" type="string | number">
      Start of the window.
    </ParamField>

    <ParamField path="to" type="string | number">
      End of the window.
    </ParamField>

    <ParamField path="startDate" type="string | number">
      Alias for `from`.
    </ParamField>

    <ParamField path="endDate" type="string | number">
      Alias for `to`.
    </ParamField>
  </Expandable>
</ParamField>

## campaign\_generate\_ai\_sequence

<Badge color="orange">Write</Badge>

Ask the platform's own AI to draft a whole campaign — copy and multi-step sequence — from a brief, and create it as a draft. Requires an AI provider connected in the web app under Settings - Integrations. Use this when the user wants the platform to write the sequence for them; to author one yourself, use `flow_set`.

### Parameters

<ParamField path="title" type="string" required>
  Campaign name.
</ParamField>

<ParamField path="goal" type="string" required>
  What the campaign should achieve, e.g. "book discovery calls".
</ParamField>

<ParamField path="targetPersona" type="string" required>
  Who is being targeted, e.g. "Heads of RevOps at Series B SaaS".
</ParamField>

<ParamField path="industry" type="string" required>
  Industry.
</ParamField>

<ParamField path="productDescription" type="string" required>
  What you are offering, in a sentence or two.
</ParamField>

<ParamField path="tone" type="string" required>
  Voice of the copy, e.g. "friendly", "direct", "consultative".
</ParamField>

<ParamField path="keyPoints" type="string" required>
  Proof points or hooks the copy should work in.
</ParamField>

<ParamField path="stepCount" type="integer (1–10)" required>
  How many steps the sequence should have.
</ParamField>

<ParamField path="country" type="string">
  Country.
</ParamField>

## campaign\_get

<Badge color="blue">Read-only</Badge>

Everything about one campaign: settings, schedule, limits, attached accounts, lead source, live counters and the flow outline. This is the tool to call before changing anything — it also reports what is still missing before the campaign can launch, in `_readiness.blockers`, which must be empty before `campaign_launch`. Read `status` here before choosing how to edit copy: `flow_set` for a DRAFTED campaign, `sequence_update` only once it is ACTIVE or PAUSED. A settings-and-counters snapshot: for the sequence in detail use `flow_get`, for performance `analytics_campaign`, and for the people `lead_list`.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="includeFlow" type="boolean" default="true">
  Include a readable outline of the campaign sequence.
</ParamField>

## campaign\_launch

<Badge color="orange">Write</Badge> <Badge color="red">Destructive</Badge>

<Warning>Marked destructive in the protocol — your MCP client asks for confirmation before running it.</Warning>

Start a campaign. THIS BEGINS SENDING REAL OUTREACH to real people from the connected LinkedIn account and mailboxes — invitations, messages and emails go out on the configured schedule. Run `campaign_get` first and clear every blocker: a saved flow, a lead source, a sending account, and (for CSV campaigns) a finished import. Show the user the full sequence and the audience and get an explicit yes in the conversation before calling — not an assumed one. Launch rebuilds every step from the saved flow graph, so any `sequence_update` edit made while the campaign was a draft is overwritten here; fix a draft's copy with `flow_set` instead. This is the only tool that starts a campaign. Pausing or resuming one afterwards has no tool at all and happens in the web app.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="skipPreflight" type="boolean" default="false">
  Skip the local readiness check and let the backend decide. Only useful if the check is wrong.
</ParamField>

## campaign\_list

<Badge color="blue">Read-only</Badge>

Campaigns in your account, newest first, 20 per page. Use `status` to filter — DRAFTED campaigns are the ones still being built, ACTIVE ones are sending right now. DELETED campaigns never appear here, which is why a deletion looks like a disappearance. The list view, a few fields each: for one campaign in full use `campaign_get`, and for performance `analytics_campaign`. Passing `userId` to read a sub-account's campaigns is accepted only from an account owner.

### Parameters

<ParamField path="status" type="ACTIVE | PAUSED | FAILED | DELETED | COMPLETED | ARCHIVED | DRAFTED">
  Filter by lifecycle status.
</ParamField>

<ParamField path="keyword" type="string">
  Search campaign titles.
</ParamField>

<ParamField path="page" type="integer (min 1)" default="1">
  1-indexed page number.
</ParamField>

<ParamField path="userId" type="string">
  Sub-account owner id. Omit for your own campaigns.
</ParamField>

## campaign\_logs

<Badge color="blue">Read-only</Badge>

Chronological record of everything that happened to a campaign: created, started, paused, resumed, lead sources added, settings changed, limits hit. Changes to the CAMPAIGN, written by whoever made them — the audit trail to read when a user asks why a campaign stopped or who changed a limit. Not what happened to the prospects: that is `activity_list`, `lead_get` or `sequence_step_stats`.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

## campaign\_preview\_message

<Badge color="blue">Read-only</Badge>

Render a draft message against a real lead from the campaign so you can see how the merge fields resolve before committing the copy to a step. Nothing is sent and nothing is saved — this is the safe way to check a \{\{placeholder}} actually resolves, since an unknown one renders empty rather than failing. Save the copy with `flow_set`; to put a real email in front of yourself instead, `campaign_send_test_email`.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="message" type="string" required>
  Draft copy, including \{\{firstName}}-style placeholders.
</ParamField>

## campaign\_send\_test\_email

<Badge color="orange">Write</Badge> <Badge color="red">Destructive</Badge>

<Warning>Marked destructive in the protocol — your MCP client asks for confirmation before running it.</Warning>

Send one real email to an address you control, using a campaign mailbox, so you can check rendering and deliverability before launch. This does send mail: show the user the recipient, subject and body and get an explicit yes first. Only ever to an address they control — it is not a way to message a prospect, and there is no tool for that. To check merge fields without sending anything, use `campaign_preview_message`.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="emailAccountId" type="string" required>
  Mailbox to send from. See `email_account_list`.
</ParamField>

<ParamField path="email" type="string (email)" required>
  Where to send the test. Use your own address.
</ParamField>

<ParamField path="content" type="string" required>
  Email body.
</ParamField>

<ParamField path="subject" type="string">
  Subject line.
</ParamField>

<ParamField path="emailAsText" type="boolean">
  Send as plain text rather than HTML.
</ParamField>

## campaign\_set\_source

<Badge color="orange">Write</Badge> <Badge color="red">Destructive</Badge>

<Warning>Marked destructive in the protocol — your MCP client asks for confirmation before running it.</Warning>

Point a DRAFTED campaign at where its prospects come from: a LinkedIn/Sales Navigator search URL, a group, an event, a post, or a CRM segment. For an ACTIVE campaign use `campaign_add_prospects` instead — that adds to the existing pool rather than replacing the source.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="url" type="string">
  A LinkedIn LIST url — a basic search, a Sales Navigator (`/sales/`) search, a Recruiter (`/talent/`) search, or a group / event / post. Not a single profile. Required unless using a CRM source.
</ParamField>

<ParamField path="surface" type="sales-navigator | recruiter | basic">
  Assert which LinkedIn surface the url belongs to. The call is rejected if the url does not match, the same way the web app validates its Sales Navigator and Recruiter tabs. Omit to detect it.
</ParamField>

<ParamField path="type" type="enum (9 values)">
  Override the inferred source type. Use "hubspot" or "ghl" for CRM pulls.
</ParamField>

<ParamField path="field" type="string">
  CRM sources: the contact property holding the LinkedIn profile URL.
</ParamField>

<ParamField path="query" type="string">
  CRM sources: the segment / list / filter query to pull.
</ParamField>

## campaign\_set\_status

<Badge color="orange">Write</Badge>

Pause a running campaign, or resume one that is paused. PAUSED halts sending immediately; pending steps stay queued and pick up where they left off when it resumes. ACTIVE starts real outreach again, so ASK THE USER before resuming — the campaign may have been paused for a reason they know and you do not. Nothing is destroyed either way, so your client will not prompt for you: the confirmation has to be one you asked for. Pausing needs no ceremony — it only stops sending, and is undone by resuming. Deliberately narrower than the `status` field it writes. It will not ARCHIVE or COMPLETE a campaign — those are web-app housekeeping — and it will not DELETE one, which is `campaign_delete`. It also refuses to resume anything that is not already PAUSED: `updateCampaign` writes the field blindly, so setting ACTIVE on a DRAFTED campaign would mark it live without a lead source, a saved flow, a sending account or materialised sequences, none of which this path checks. A campaign that has never run is started with `campaign_launch`, which validates all of that first.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="status" type="PAUSED | ACTIVE" required>
  PAUSED halts sending. ACTIVE resumes a paused campaign, and is refused for any other current status.
</ParamField>

## campaign\_update

<Badge color="orange">Write</Badge>

Change a campaign's SETTINGS: title, sending accounts, schedule, daily limits, timezone and every safety toggle. Only the fields you pass are changed. Attaching accounts is done here: one `linkedAccountId` for LinkedIn steps, and `emailAccountIds` — a list — for EMAIL steps. Ask the user which accounts when there is a choice. NOT this tool: campaign status. It cannot start, pause, resume, archive or delete a campaign, and there is no `status` parameter. To start one use `campaign_launch`; to remove one use `campaign_delete`. Pausing, resuming and archiving are web-app only and have no tool at all — say so rather than looking for a substitute. Nor does it touch the sequence (`flow_set`) or the audience (`campaign_set_source`). One side effect worth knowing: changing `linkedAccountId` rewrites that account onto every lead already in the campaign, not just future ones.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="title" type="string">
  Short label.
</ParamField>

<ParamField path="linkedAccountId" type="string">
  The ONE LinkedIn account this campaign sends from. Required for any LinkedIn step. A campaign cannot use two. If `linkedin_account_list` returns more than one, ask the user which — do not pick for them.
</ParamField>

<ParamField path="emailAccountIds" type="string[]">
  Mailboxes for EMAIL steps. Unlike the LinkedIn account, several are allowed and sends rotate across them. Only attach these if the user wants email steps, and ask which mailboxes.
</ParamField>

<ParamField path="timezone" type="string">
  IANA timezone, e.g. "America/New\_York". Governs the schedule.
</ParamField>

<ParamField path="schedule" type="object">
  Sending window per weekday, keyed 0 (Sunday) to 6 (Saturday), in the campaign timezone.

  <Expandable title="properties">
    <ParamField path="0" type="object">
      Sunday
    </ParamField>

    <ParamField path="1" type="object">
      Monday
    </ParamField>

    <ParamField path="2" type="object">
      Tuesday
    </ParamField>

    <ParamField path="3" type="object">
      Wednesday
    </ParamField>

    <ParamField path="4" type="object">
      Thursday
    </ParamField>

    <ParamField path="5" type="object">
      Friday
    </ParamField>

    <ParamField path="6" type="object">
      Saturday
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="campaginLimits" type="object">
  Per-day caps per step type. Note the field spelling.

  <Expandable title="properties">
    <ParamField path="CONNECT" type="integer (min 0)">
      Connection invites per day.
    </ParamField>

    <ParamField path="MESSAGE" type="integer (min 0)">
      LinkedIn messages per day.
    </ParamField>

    <ParamField path="INMAILS" type="integer (min 0)">
      InMails per day.
    </ParamField>

    <ParamField path="ENGAGEMENT" type="integer (min 0)">
      Profile engagements per day.
    </ParamField>

    <ParamField path="FOLLOW" type="integer (min 0)">
      Follows per day.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="tags" type="string[]">
  Tag ids applied to every lead in this campaign — this identifies the campaign's leads, so it should be a tag belonging to THIS campaign. Never reuse another campaign's tag: the two campaigns' leads then become indistinguishable. Mint one with `tag_create` (short label, interest NEUTRAL) and pass its id. Pass \[] to remove all tags.
</ParamField>

<ParamField path="assignTo" type="object (free-form)">
  Assign leads to team members. Shape mirrors the web app.
</ParamField>

<ParamField path="leadsPriority" type="string">
  Ordering strategy for working the lead queue, e.g. "newest" / "oldest".
</ParamField>

<ParamField path="stopOnReply" type="boolean">
  Halt a lead's sequence as soon as they reply. Default true.
</ParamField>

<ParamField path="skipProfiles" type="boolean">
  Skip prospects you already have an open conversation with.
</ParamField>

<ParamField path="uniqueProfiles" type="boolean">
  Never enrol the same profile in two campaigns. Default true.
</ParamField>

<ParamField path="premiumProfiles" type="boolean">
  Only target LinkedIn Premium / Open Profile members.
</ParamField>

<ParamField path="connectionOutreach" type="boolean">
  Target existing 1st-degree connections instead of new ones.
</ParamField>

<ParamField path="snOutreach" type="boolean">
  Use Sales Navigator messaging. Requires a Premium LinkedIn account.
</ParamField>

<ParamField path="prioritizeNewLeads" type="boolean">
  Work newly-found prospects before older ones.
</ParamField>

<ParamField path="reload" type="boolean">
  Re-run the search periodically to pull in newly matching prospects.
</ParamField>

<ParamField path="trackOpens" type="boolean">
  EMAIL steps: insert an open-tracking pixel.
</ParamField>

<ParamField path="trackClicks" type="boolean">
  EMAIL steps: rewrite links for click tracking.
</ParamField>

<ParamField path="emailAsText" type="boolean">
  Send email as plain text. Better deliverability, no tracking.
</ParamField>

<ParamField path="pauseCampaign" type="boolean">
  Pause the campaign without changing its status.
</ParamField>

<ParamField path="scheduledAt" type="string | number">
  Future timestamp to auto-start the campaign, instead of launching it now with `campaign_launch`.
</ParamField>

<ParamField path="agentId" type="string">
  AI agent that answers replies in this campaign's inbox. Pass null to detach it. Never set this on your own: an agent writes to real prospects without further approval. Ask the user whether they want one, and offer both routes — pick an existing agent from `agent_list`, or build one with `agent_upsert`, give it material with `kb_upsert` and `kb_attach`, then `agent_train`. A campaign with no agent is perfectly normal; replies just come to the inbox.
</ParamField>

## campaign\_upload\_leads

<Badge color="orange">Write</Badge>

Bulk-load prospects into a campaign from parsed CSV rows. `header` maps each column name to a platform field — profileUrl, salesNavUrl, recruiterUrl, email, firstName, lastName, fullName, personalization, phone, website, or "customVariable" to keep it as a merge field. Rows with neither a profile URL nor an email are skipped silently. Import runs asynchronously; the campaign is only launchable once `isFiltered` flips true. Use this when the user has a list in hand. When they describe an audience instead, the audience is a LinkedIn search and belongs in `campaign_set_source` — build the URL with `search_url_build`. For a campaign that is already running, neither applies: that is `campaign_add_prospects`.

### Parameters

<ParamField path="campaignId" type="string" required>
  Campaign id, from `campaign_list` or `campaign_create`.
</ParamField>

<ParamField path="header" type="object (free-form)" required>
  \{ "CSV Column Name": "targetField" }. Use "customVariable" for anything you want as a merge field.
</ParamField>

<ParamField path="leads" type="array of object (free-form)" required>
  Row objects keyed by the CSV column names used in `header`.
</ParamField>

<ParamField path="removeDuplicates" type="boolean" default="true">
  Skip prospects already enrolled in another active or paused campaign on this account.
</ParamField>

## search\_url\_build

<Badge color="blue">Read-only</Badge>

Turn an audience description into a LinkedIn or Sales Navigator people-search URL, so a campaign source can be described rather than pasted. Returns the url plus what it managed to express — hand it to `campaign_set_source`.

What it can build: job titles (included and excluded) and free-text keywords with boolean operators. What it CANNOT build: geography, industry, company size, seniority and years-in-role. Sales Navigator only accepts those as numeric ids from its own typeahead (`id:103644278` is United States), they cannot be derived from a name, and a wrong id silently searches the wrong audience. For those, either ask the user to paste a Sales Navigator URL with the filters already set, or pass the ids through `extraFilters` if the user supplies them. Never guess one.

Recruiter (`/talent/`) URLs cannot be built at all — ask the user for one.

### Parameters

<ParamField path="surface" type="basic | sales-navigator" required>
  "basic" is ordinary LinkedIn search; "sales-navigator" needs a Sales Navigator seat.
</ParamField>

<ParamField path="keywords" type="string">
  Free text. Supports boolean operators, e.g. '"chatbot" OR "AI agent"'.
</ParamField>

<ParamField path="titles" type="string[]">
  Job titles to include, as plain text.
</ParamField>

<ParamField path="excludeTitles" type="string[]">
  Job titles to exclude. Sales Navigator only — basic search cannot express an exclusion.
</ParamField>

<ParamField path="company" type="string">
  Basic search only: current company, free text.
</ParamField>

<ParamField path="school" type="string">
  Basic search only: school, free text.
</ParamField>

<ParamField path="firstName" type="string">
  Basic search only.
</ParamField>

<ParamField path="lastName" type="string">
  Basic search only.
</ParamField>

<ParamField path="extraFilters" type="object[]">
  Id-based filters, only when the USER supplied the ids or they came from a URL they pasted. Do not populate this from memory.

  <Expandable title="properties">
    <ParamField path="type" type="string" required>
      Sales Navigator filter type, e.g. REGION, INDUSTRY, COMPANY\_HEADCOUNT.
    </ParamField>

    <ParamField path="values" type="object[]" required>
      Values for this filter, each with the id LinkedIn assigns it.
    </ParamField>
  </Expandable>
</ParamField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.