# nv.saveLead

Save a person as a lead in Sales Navigator, optionally adding them to one of your lead lists.

> The API Reference is also the SDK and CLI reference. Consecutive code fences marked `tab=HTTP`, `tab=Node`, `tab=Python` and `tab=CLI` are the same call on each surface (a fence marked `tab=HTTP,CLI` is the same text for both), and a block between `:::surface <names>` and `:::` applies only to the surfaces it names. Identifiers in the text are written as in Node and in HTTP JSON (camelCase); the Python SDK spells methods, parameters and result attributes in snake_case (`sendMessage` → `send_message`, `reconnectionLink` → `reconnection_link`), while names inside HTTP JSON stay camelCase.

Save a person as a lead in Sales Navigator and, optionally, add them to one of your custom lead lists. Sales Navigator raises lead alerts for the leads you save. To read only alerts about subjects you saved, set `filter.excludeSuggested` to `true` in [`nv.retrieveAlerts`](/docs/action-nv-retrieve-alerts). An alert's `subject.url` can be passed straight to this action.

An active Sales Navigator subscription is required. To find a list's ID, call [`nv.retrieveLists`](/docs/action-nv-retrieve-lists) with `type` set to `lead`. To create a new lead list, call [`nv.createList`](/docs/action-nv-create-list) and use the `id` it returns.

:::surface node,python
In the SDK this is the `nvSaveLead` method. It takes the parameters below except `label`, which exists only in workflow JSON. It returns no `data`: a failed action comes back in `errors`, with one of the error types below.
:::

:::surface cli
The command is `linkedin navigator person save`. Its argument and flag are listed below.
:::

## Constraints

> ⏺️ **Root Start:** allowed, when `personHashedUrl` parameter is provided.

> ⬆️ **Parent Actions:** [nv.openPersonPage](/docs/action-nv-open-person-page), [nv.doForPeople](/docs/action-nv-do-for-people) under [nv.searchPeople](/docs/action-nv-search-people), [nv.retrieveCompanyEmployees](/docs/action-nv-retrieve-company-employees) or [nv.retrieveCompanyDMs](/docs/action-nv-retrieve-company-dms).

> ⬇️ **Child Actions:** N/A.

## Parameters

```json tab=HTTP
{
  "actionType": "nv.saveLead",
  "label": "saveLead1",
  "personHashedUrl": "https://www.linkedin.com/in/SInQBmjJ015eLr8",
  "listId": "7420000000000000001"
}
```

```typescript tab=Node
const workflow = await linkedapi.nvSaveLead.execute({
  personHashedUrl: "https://www.linkedin.com/in/SInQBmjJ015eLr8",
  listId: "7420000000000000001"
});

const { errors } = await linkedapi.nvSaveLead.result(workflow.workflowId);
```

```python tab=Python
from linkedapi import NvSaveLeadParams

workflow = linkedapi.nv_save_lead.execute(
    NvSaveLeadParams(
        person_hashed_url="https://www.linkedin.com/in/SInQBmjJ015eLr8",
        list_id="7420000000000000001",
    )
)

result = linkedapi.nv_save_lead.result(workflow.workflow_id)
```

```bash tab=CLI
linkedin navigator person save https://www.linkedin.com/in/SInQBmjJ015eLr8 \
  --list-id 7420000000000000001 \
  --json
```

In AI assistants, the MCP tool is `nv_save_lead`. The n8n action is **Save lead in Sales Navigator**; the Make module is **Save Lead in Sales Navigator**.

| Parameter | Description |
| --- | --- |
| `label` | Optional label included in workflow completion. |
| `personHashedUrl` | Required for root start, forbidden for parent start. LinkedIn URL of the person, in any form [`nv.openPersonPage`](/docs/action-nv-open-person-page#accepted-urls) accepts: a [hashed](/faq/what-are-hashed-url-and-public-url) URL, an alert's `subject.url` (`/sales/lead/…`), or a public profile URL (`linkedin.com/in/<vanity>`), which costs one extra page load. Under a parent action, the person comes from the parent. |
| `listId` | Optional. ID of one of your custom lead lists, as returned in `id` by [`nv.retrieveLists`](/docs/action-nv-retrieve-lists) or [`nv.createList`](/docs/action-nv-create-list). Pass it as a string. Omit it to save the lead without changing any list. **More than 10 lead lists, for now:** Sales Navigator's save menu shows lists ten at a time. If you have more than 10 lead lists and the requested list is not among those the menu shows, the call fails with `unexpectedError`. The lead may already be saved by then, but is not added to that list. This is a current limitation. |

:::surface cli
| Arg | Required | Description |
| --- | --- | --- |
| `url` | yes | LinkedIn URL of the person: hashed, an alert's `subject.url`, or public |

| Flag | Description |
| --- | --- |
| `--list-id` | ID of one of your custom lead lists. Omit to save without changing any list. |
:::

## Saving behaviour

- **Saved, and in the list you name.** The action makes sure the person is a saved lead. With `listId`, it also makes sure the lead is in that one list and leaves the lead's other lists as they are. Without `listId`, no list changes.
- **Safe to repeat.** Saving a lead that is already saved, or already in the requested list, succeeds without changing anything.
- **The lead's company may be saved too.** Saving a lead can make Sales Navigator also save the lead's current company as an account. This is Sales Navigator's own behaviour.
- **Which lists you can save to.** `listId` must be one of your custom lead lists. [`nv.retrieveLists`](/docs/action-nv-retrieve-lists) also returns Sales Navigator's system lists, such as Recommended Leads, but Sales Navigator does not offer them as save targets. Any other ID returns `listNotFound`, and nothing is written. The same applies when another of your lead lists has exactly the same name: the save menu shows lists by name only, so rename one of them first. [`nv.createList`](/docs/action-nv-create-list) never creates a lead list with a name you already use.
- **Changes can take up to a few minutes to appear.** Sales Navigator can take up to a few minutes to reflect a change. A call that conflicts with a change you just made through Linked API, such as unsaving a lead you have just saved, may fail with `unexpectedError`; retry it a little later.
- **English interface only, for now.** This is a current limitation: saving and unsaving work only with an English Sales Navigator interface. On a German, Spanish, French or Portuguese interface, the call fails with `interfaceLanguageNotSupported`.

To take the lead out of one list and keep them saved, use [`nv.removeLeadFromList`](/docs/action-nv-remove-lead-from-list); to unsave them, use [`nv.unsaveLead`](/docs/action-nv-unsave-lead).

## Saving from search results

Under [`nv.doForPeople`](/docs/action-nv-do-for-people), whose parent is [`nv.searchPeople`](/docs/action-nv-search-people), [`nv.retrieveCompanyEmployees`](/docs/action-nv-retrieve-company-employees) or [`nv.retrieveCompanyDMs`](/docs/action-nv-retrieve-company-dms), the action saves each person straight from the parent's result list, without opening their page. If that list is no longer open when the save runs, for example because an earlier action for the same person opened their page, the action saves on the person's page instead. Saving 20 search results costs the search result pages instead of 20 extra profile page loads, so your LinkedIn account does far less browsing for the same result. How many people are saved is set by the parent action's `limit`.

Under [`nv.openPersonPage`](/docs/action-nv-open-person-page), the action saves the person whose page is already open, so you can read their details, message them and save them in one workflow.

[`nv.unsaveLead`](/docs/action-nv-unsave-lead) is not available under `nv.doForPeople`.

**Workflow:**

```json tab=HTTP
{
  "actionType": "nv.searchPeople",
  "term": "Head of Sales",
  "limit": 2,
  "filter": {
    "locations": ["London"]
  },
  "then": {
    "actionType": "nv.doForPeople",
    "then": {
      "actionType": "nv.saveLead",
      "listId": "7420000000000000001"
    }
  }
}
```

```typescript tab=Node
const workflow = await linkedapi.customWorkflow.execute({
  actionType: "nv.searchPeople",
  term: "Head of Sales",
  limit: 2,
  filter: {
    locations: ["London"]
  },
  then: {
    actionType: "nv.doForPeople",
    then: {
      actionType: "nv.saveLead",
      listId: "7420000000000000001"
    }
  }
});

const { data, errors } = await linkedapi.customWorkflow.result(workflow.workflowId);
```

```python tab=Python
workflow = linkedapi.custom_workflow.execute(
    {
        "actionType": "nv.searchPeople",
        "term": "Head of Sales",
        "limit": 2,
        "filter": {
            "locations": ["London"],
        },
        "then": {
            "actionType": "nv.doForPeople",
            "then": {
                "actionType": "nv.saveLead",
                "listId": "7420000000000000001",
            },
        },
    }
)

result = linkedapi.custom_workflow.result(workflow.workflow_id)
```

```bash tab=CLI
linkedin workflow run <<'EOF'
{
  "actionType": "nv.searchPeople",
  "term": "Head of Sales",
  "limit": 2,
  "filter": {
    "locations": ["London"]
  },
  "then": {
    "actionType": "nv.doForPeople",
    "then": {
      "actionType": "nv.saveLead",
      "listId": "7420000000000000001"
    }
  }
}
EOF
```

:::surface http
**Completion:**
:::

:::surface node,python
**Completion** – `result()` returns this whole completion in `data`:
:::

:::surface cli
**Completion** – `linkedin workflow run` prints this whole completion as `data`:
:::

```json
{
  "actionType": "nv.searchPeople",
  "success": true,
  "data": [
    {
      "name": "Jane Smith",
      "urn": "urn:li:member:123456789",
      "hashedUrl": "https://www.linkedin.com/in/SInQBmjJ015eLr8",
      "position": "Head of Sales",
      "location": "London",
      "avatarUrl": null,
      "viewerState": { "connectionDegree": "2nd" },
      "then": [
        {
          "actionType": "nv.saveLead",
          "success": true
        }
      ]
    },
    {
      "name": "Tom Brown",
      "urn": "urn:li:member:987654321",
      "hashedUrl": "https://www.linkedin.com/in/ACoAA2DdsSV83B48",
      "position": "Head of Sales EMEA",
      "location": "London",
      "avatarUrl": null,
      "viewerState": { "connectionDegree": "3rd+" },
      "then": [
        {
          "actionType": "nv.saveLead",
          "success": true
        }
      ]
    }
  ]
}
```

## Result options

```json
{
  "actionType": "nv.saveLead",
  "label": "saveLead1",
  "success": true
}
```

A successful save has no `data`. `label` is included only if specified in the action parameters.

## Error result

An unsuccessful action returns `success: false` with an `error` object:

```json
{
  "actionType": "nv.saveLead",
  "label": "saveLead1",
  "success": false,
  "error": {
    "type": "listNotFound",
    "message": "The list is not available for this subject in Sales Navigator."
  }
}
```

Possible `error.type` values:

- `noSalesNavigator` — the account does not have an active Sales Navigator subscription.
- `personNotFound` — the provided URL is not an existing LinkedIn person. This includes a public profile URL that leads to no LinkedIn profile.
- `listNotFound` — `listId` is not one of your custom lead lists. This is checked before anything is written. Rarely, a valid list is missing from the lead's save menu; the lead may then already be saved when this error is returned.
- `interfaceLanguageNotSupported` — the account's Sales Navigator interface is German, Spanish, French or Portuguese rather than English. Nothing is changed; this is a current limitation (see above).
- `unexpectedError` — the save could not be completed. This includes a call that conflicts with a change you just made through Linked API: Sales Navigator can take up to a few minutes to reflect a change, so retry it a little later. It also includes a `listId` that the save menu did not show when you have more than 10 lead lists (see [`listId`](#parameters)).
