Linkedin logo

Linkedin

Organization
Linked-API
linkedin

General-purpose LinkedIn automation – fetch profiles, search people and companies, send messages, manage connections, create posts, and more. Use when the user wants to interact with LinkedIn.

Overview

PublisherLinked-API
Repositorylinkedin-skills
Skill namelinkedin
Stars
107
Forks
19
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by Linked-API on GitHub. Read the source before you install it.

Installation

Install the Linkedin AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/Linked-API/linkedin-skills/tree/main/linkedin
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/Linked-API/linkedin-skills.git /tmp/linkedin-skills
mkdir -p .claude/skills
cp -r /tmp/linkedin-skills/linkedin .claude/skills/linkedin
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Linkedin in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Linkedin on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Linkedin is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

LinkedIn Skill

You have access to linkedin – a CLI tool for LinkedIn automation. Use it to fetch profiles, search people and companies, send messages, manage connections, create posts, react, comment, and more.

Each command sends a request to Linked API, which runs a real cloud browser to perform the action on LinkedIn. Operations are not instant – expect 30 seconds to several minutes depending on complexity.

If linkedin is not available, install it:

bash
npm install -g @linkedapi/linkedin-cli

Authentication

If a command fails with exit code 2 (authentication error), ask the user to set up their account:

  1. Go to app.linkedapi.io and sign up or log in
  2. Connect their LinkedIn account
  3. Copy the Linked API Token and Identification Token from the dashboard

Once the user provides the tokens, run:

bash
linkedin setup --linked-api-token=TOKEN --identification-token=TOKEN

Global Flags

Always use --json and -q for machine-readable output:

bash
LINKEDAPI_CLIENT=skill:linkedin linkedin <command> --json -q

When using this skill, run every linkedin ... example below with the LINKEDAPI_CLIENT=skill:linkedin prefix so Linked API can attribute usage to the skill.

FlagDescription
--jsonStructured JSON output
--quiet / -qSuppress stderr progress messages
--fields name,url,...Select specific fields in output
--no-colorDisable colors
--account "Name"Use a specific account for this command

Output Format

Success:

json
{"success": true, "data": {"name": "John Doe", "headline": "Engineer"}}

Error:

json
{"success": false, "error": {"type": "personNotFound", "message": "Person not found"}}

Exit code 0 means the API call succeeded – always check the success field for the action outcome. Non-zero exit codes indicate infrastructure errors:

Exit CodeMeaning
0Success (check success field – action may have returned an error like "person not found")
1General/unexpected error
2Missing or invalid tokens
3Subscription/plan required
4LinkedIn account issue
5Invalid arguments
6Rate limited
7Network error
8Workflow timeout (workflowId returned for recovery)

Commands

Fetch a Person Profile

bash
linkedin person fetch <url> [flags] --json -q

Optional flags to include additional data:

  • --experience – work history
  • --education – education history
  • --skills – skills list
  • --languages – languages
  • --posts – recent posts (with --posts-limit N, --posts-since TIMESTAMP)
  • --comments – recent comments (with --comments-limit N, --comments-since TIMESTAMP)
  • --reactions – recent reactions (with --reactions-limit N, --reactions-since TIMESTAMP)

Only request additional data when needed – each flag increases execution time.

bash
# Basic profile
linkedin person fetch https://www.linkedin.com/in/username --json -q

# With experience and education
linkedin person fetch https://www.linkedin.com/in/username --experience --education --json -q

# With last 5 posts
linkedin person fetch https://www.linkedin.com/in/username --posts --posts-limit 5 --json -q

Endorse a Person's Skills

bash
linkedin person endorse <url> --skill 'Project Management' --json -q
linkedin person endorse <url> --pattern manage --pattern '^scrum$' --json -q
linkedin person endorse <url> --all --json -q

Choose exactly one of --skill, --pattern or --all:

  • Use --skill for one exact skill name; letter case and extra spaces are ignored.
  • Use repeatable --pattern to select skills matching any of the patterns. Patterns use RE2, are case-insensitive and match anywhere in the name. Anchor with ^…$ to match a whole name. Provide 1-20 patterns, each 1-200 characters; lookaround and backreferences are unsupported.
  • Use --all only when the user wants every skill endorsed. It omits the patterns parameter; never send an empty patterns array.

Skill names are in the profile owner's language, regardless of your own LinkedIn language. Fetch the profile with --skills first when you need to discover the names; a German profile may list Projektmanagement rather than Project Management.

Only 1st-degree connections can receive endorsements. An already-endorsed skill stays endorsed and counts as success. Each successful endorsement, including an existing one, counts toward the account's stEndorsements limit. With --pattern or --all, check every item's success and error.type in data: a failed skill does not stop the others, and limitExceeded can affect only part of the result.

Search People

bash
linkedin person search [flags] --json -q
FlagDescription
--termSearch keyword or phrase
--limitMax results
--first-nameFilter by first name
--last-nameFilter by last name
--positionFilter by job position
--locationsComma-separated locations
--industriesComma-separated industries
--current-companiesComma-separated current company names
--previous-companiesComma-separated previous company names
--schoolsComma-separated school names
--connection-degreesComma-separated connection degrees: 1st, 2nd, 3rd+
bash
linkedin person search --term "product manager" --locations "San Francisco" --json -q
linkedin person search --current-companies "Google" --position "Engineer" --limit 20 --json -q

Fetch a Company

bash
linkedin company fetch <url> [flags] --json -q

Optional flags:

  • --employees – include employees
  • --dms – include decision makers
  • --posts – include company posts

Employee filters (require --employees):

FlagDescription
--employees-limitMax employees to retrieve
--employees-first-nameFilter by first name
--employees-last-nameFilter by last name
--employees-positionFilter by position
--employees-locationsComma-separated locations
--employees-industriesComma-separated industries
--employees-schoolsComma-separated school names
--employees-connection-degreesComma-separated connection degrees: 1st, 2nd, 3rd+
FlagDescription
--dms-limitMax decision makers to retrieve (requires --dms)
--posts-limitMax posts to retrieve (requires --posts)
--posts-sincePosts since ISO timestamp (requires --posts)
bash
# Basic company info
linkedin company fetch https://www.linkedin.com/company/name --json -q

# With employees filtered by position
linkedin company fetch https://www.linkedin.com/company/name --employees --employees-position "Engineer" --json -q

# With decision makers and posts
linkedin company fetch https://www.linkedin.com/company/name --dms --posts --posts-limit 10 --json -q

Search Companies

bash
linkedin company search [flags] --json -q
FlagDescription
--termSearch keyword
--limitMax results
--sizesComma-separated sizes: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+
--locationsComma-separated locations
--industriesComma-separated industries
bash
linkedin company search --term "fintech" --sizes "11-50,51-200" --json -q

Send a Message

bash
linkedin message send <person-url> '<text>' --json -q

Text up to 1900 characters. Wrap the message in single quotes to avoid shell interpretation issues.

bash
linkedin message send https://www.linkedin.com/in/username 'Hey, loved your latest post!' --json -q

Inbox

To read messages use inbox get. Call message get only when you need a person's earlier history, and never repeat it to check for new messages.

Enable inbox monitoring once per account, before sending messages whose replies you need – it captures only messages that arrive after it is on:

bash
linkedin inbox sync --json -q          # standard inbox
linkedin inbox sync --nv --json -q     # Sales Navigator inbox

New messages from everyone, with an advancing --since:

bash
linkedin inbox get --since 2024-01-15T10:30:00Z --json -q

The whole known conversation with one person, including history loaded by message get:

bash
linkedin inbox get --person https://www.linkedin.com/in/username --json -q

With --person, the output has messages and threads. Each thread has historyComplete: if it is false and you need earlier messages, run message get <person-url> once, then inbox get --person again. A hashed person URL (personHashedUrl from a message) always matches; a public URL matches only once Linked API knows it, so prefer the hashed URL when messages show personPublicUrl: null. Message times are whole minutes: to check for a reply, pass --type of your message and --since a few minutes before it, take the earliest us message in the result (the one you sent, not a later follow-up) and count a them message that is not earlier than it; if your message is not in the result yet, the reply is not known yet.

Get Conversation

bash
linkedin message get <person-url> [--since TIMESTAMP] --json -q

Loads the person's earlier history on the first call, which may take longer; subsequent calls are faster. Prefer linkedin inbox get --person <url> to read messages – use this only when you need history from before inbox monitoring was enabled.

bash
linkedin message get https://www.linkedin.com/in/username --json -q
linkedin message get https://www.linkedin.com/in/username --since 2024-01-15T10:30:00Z --json -q

Connection Management

Check connection status
bash
linkedin connection status <url> --json -q
Send connection request
bash
linkedin connection send <url> [--note 'text'] [--email user@example.com] --json -q
List connections
bash
linkedin connection list [flags] --json -q
FlagDescription
--limitMax connections to return
--sinceOnly connections made since ISO timestamp (only works when no filter flags are used)
--first-nameFilter by first name
--last-nameFilter by last name
--positionFilter by job position
--locationsComma-separated locations
--industriesComma-separated industries
--current-companiesComma-separated current company names
--previous-companiesComma-separated previous company names
--schoolsComma-separated school names
bash
linkedin connection list --limit 50 --json -q
linkedin connection list --current-companies "Google" --position "Engineer" --json -q
linkedin connection list --since 2024-01-01T00:00:00Z --json -q
List pending outgoing requests
bash
linkedin connection pending --json -q
List incoming connection requests

Invitations that others have sent to you (received requests).

bash
linkedin connection requests --json -q
Accept an incoming request
bash
linkedin connection accept <url> --json -q
Ignore an incoming request
bash
linkedin connection ignore <url> --json -q
Withdraw a pending request
bash
linkedin connection withdraw <url> [--no-unfollow] --json -q

By default, withdrawing also unfollows the person. Use --no-unfollow to keep following.

Remove a connection
bash
linkedin connection remove <url> --json -q

Posts

Fetch a post
bash
linkedin post fetch <url> [flags] --json -q
FlagDescription
--commentsInclude comments
--reactionsInclude reactions
--comments-limitMax comments to retrieve (requires --comments)
--comments-sortSort order: mostRelevant or mostRecent (requires --comments)
--comments-repliesInclude replies to comments (requires --comments)
--reactions-limitMax reactions to retrieve (requires --reactions)
bash
linkedin post fetch https://www.linkedin.com/posts/username_activity-123 --json -q

# With comments sorted by most recent, including replies
linkedin post fetch https://www.linkedin.com/posts/username_activity-123 \
  --comments --comments-sort mostRecent --comments-replies --json -q
Search posts
bash
linkedin post search [flags] --json -q
FlagDescription
--termSearch keyword or phrase, up to 50 characters
--limitMax results to return, up to 100
--from-membersPeople whose posts to keep
--from-companiesCompanies whose posts to keep
--mentioning-membersPeople the post must mention
--mentioning-companiesCompanies the post must mention
--author-companiesCompanies the author works at

Each actor flag is a comma-separated list. An element is name or name:identifier, where the identifier is a URN or LinkedIn URL of that person or company and pins the filter to exactly them. A name alone may match a namesake. When an entry cannot be applied, the action fails with filterNotApplied; correct or remove it rather than retrying.

bash
linkedin post search --term "ai" --from-members "Bill Gates,Example Person:urn:li:member:123456789" --json -q
Create a post
bash
linkedin post create '<text>' [flags] --json -q
FlagDescription
--company-urlPost on behalf of a company page (requires admin access)
--attachmentsAttachment as url:type or url:type:name. Types: image, video, document. Can be specified multiple times.
--mentionOne mention, bound to @[key] in the text. Format below. Can be specified multiple times, up to 20.

Attachment limits: up to 9 images, or 1 video, or 1 document. Cannot mix types.

Mention format — write @[key] in the text, then describe that key with --mention as key:name or key:name:identifier. Everything after the second : is the identifier, so its own colons need no escaping. The identifier is optional and is one of urn:li:member:<id>, urn:li:organization:<id>, a hashed profile URL, or a hashed company URL; without it LinkedIn's first suggestion for name is used, which may not be the entity you meant. Every @[key] must have a matching --mention and vice versa, and keys cannot repeat.

bash
linkedin post create 'Excited to share our latest update!' --json -q

# With a document
linkedin post create 'Our Q4 report' \
  --attachments "https://example.com/report.pdf:document:Q4 Report" --json -q

# Mentioning a person
linkedin post create 'Huge thanks to @[author] for the write-up!' \
  --mention "author:Example Person:urn:li:member:123456789" --json -q

# Post as a company
linkedin post create 'Company announcement' \
  --company-url https://www.linkedin.com/company/name --json -q
Repost a post
bash
linkedin post repost <url> [flags] --json -q
FlagDescription
--textYour own commentary (up to 3000 characters). Without it the post is reposted as is.
--mentionOne mention, bound to @[key] in --text. Same format as for post create. Can be specified multiple times, up to 20.

The repost's own postUrl and postUrn come back, not those of the post you reposted. They are empty when the repost was published but LinkedIn did not return its address — do not retry, the repost is already live.

alreadyReposted is returned only when LinkedIn refuses an instant repost (one without --text). LinkedIn does not always refuse a repeat repost: a repost of your own post, or a repost with commentary, can be published again. Keep track of what you have already reposted instead of relying on this error.

bash
linkedin post repost https://www.linkedin.com/posts/username_activity-123 --json -q

# With commentary
linkedin post repost urn:li:activity:1234567890123456789 \
  --text 'Worth reading, especially the part on onboarding.' --json -q
React to a post
bash
linkedin post react <url> --type <reaction> [--company-url <url>] --json -q

Reaction types: like, love, support, celebrate, insightful, funny.

bash
linkedin post react https://www.linkedin.com/posts/username_activity-123 --type like --json -q

# React on behalf of a company
linkedin post react https://www.linkedin.com/posts/username_activity-123 --type celebrate \
  --company-url https://www.linkedin.com/company/name --json -q
Comment on a post
bash
linkedin post comment <url> '<text>' [--company-url <url>] --json -q

Text up to 1000 characters.

bash
linkedin post comment https://www.linkedin.com/posts/username_activity-123 'Great insights!' --json -q

# Comment on behalf of a company
linkedin post comment https://www.linkedin.com/posts/username_activity-123 'Well said!' \
  --company-url https://www.linkedin.com/company/name --json -q

Statistics

bash
# Social Selling Index
linkedin stats ssi --json -q

# Performance analytics (profile views, post impressions, search appearances)
linkedin stats performance --json -q

# API usage for a date range
linkedin stats usage --start 2024-01-01T00:00:00Z --end 2024-01-31T00:00:00Z --json -q

# Who viewed your profile
linkedin stats viewers --limit 50 --json -q

# Only views since a moment
linkedin stats viewers --since 2026-08-01T00:00:00Z --json -q

Each viewer is either identified — carrying name, publicUrl and urn (a member URN, null when LinkedIn does not expose it) — or anonymous, carrying only the description LinkedIn showed and a searchUrl you can pass to linkedin person search --url to look for them. Viewers come newest first, and viewedAt is an estimate derived from the relative age LinkedIn displays.

Sales Navigator

Requires a LinkedIn Sales Navigator subscription. Uses hashed URLs for person/company lookups.

Fetch person
bash
linkedin navigator person fetch <hashed-url> --json -q
Search people
bash
linkedin navigator person search [flags] --json -q
FlagDescription
--termSearch keyword or phrase
--limitMax results
--first-nameFilter by first name
--last-nameFilter by last name
--positionFilter by job position
--locationsComma-separated locations
--industriesComma-separated industries
--current-companiesComma-separated current company names
--previous-companiesComma-separated previous company names
--schoolsComma-separated school names
--years-of-experienceComma-separated ranges: lessThanOne, oneToTwo, threeToFive, sixToTen, moreThanTen
--connection-degreesComma-separated connection degrees: 1st, 2nd, 3rd+, groupMembers
bash
linkedin navigator person search --term "VP Marketing" --locations "United States" --json -q
linkedin navigator person search --years-of-experience "moreThanTen" --position "CEO" --json -q
Fetch company
bash
linkedin navigator company fetch <hashed-url> [flags] --json -q

Optional flags:

  • --employees – include employees
  • --dms – include decision makers

Employee filters (require --employees):

FlagDescription
--employees-limitMax employees to retrieve
--employees-first-nameFilter by first name
--employees-last-nameFilter by last name
--employees-positionsComma-separated positions
--employees-locationsComma-separated locations
--employees-industriesComma-separated industries
--employees-schoolsComma-separated school names
--employees-years-of-experienceComma-separated experience ranges
--employees-connection-degreesComma-separated connection degrees: 1st, 2nd, 3rd+, groupMembers
--dms-limitMax decision makers to retrieve (requires --dms)
bash
linkedin navigator company fetch https://www.linkedin.com/sales/company/97ural --employees --dms --json -q
linkedin navigator company fetch https://www.linkedin.com/sales/company/97ural \
  --employees --employees-positions "Engineer,Designer" --employees-locations "Europe" --json -q
Search companies
bash
linkedin navigator company search [flags] --json -q
FlagDescription
--termSearch keyword
--limitMax results
--sizesComma-separated sizes: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+
--locationsComma-separated locations
--industriesComma-separated industries
--revenue-minMin annual revenue in M USD: 0, 0.5, 1, 2.5, 5, 10, 20, 50, 100, 500, 1000
--revenue-maxMax annual revenue in M USD: 0.5, 1, 2.5, 5, 10, 20, 50, 100, 500, 1000, 1000+
bash
linkedin navigator company search --term "fintech" --sizes "11-50,51-200" --json -q
linkedin navigator company search --revenue-min 10 --revenue-max 100 --locations "United States" --json -q
Send InMail
bash
linkedin navigator message send <person-url> '<text>' --subject '<subject>' --json -q

Text up to 1900 characters. Subject up to 80 characters.

bash
linkedin navigator message send https://www.linkedin.com/in/username \
  'Would love to chat about API integrations' --subject 'Partnership Opportunity' --json -q
Get Sales Navigator conversation
bash
linkedin navigator message get <person-url> [--since TIMESTAMP] --json -q

Prefer linkedin inbox get --person <url> --type nv to read Sales Navigator messages; use this only when you need the person's earlier history.

Custom Workflows

Execute a custom workflow definition from a file, stdin, or inline:

bash
# From file
linkedin workflow run --file workflow.json --json -q

# From stdin
cat workflow.json | linkedin workflow run --json -q

# Inline
echo '{"actions":[...]}' | linkedin workflow run --json -q

Check workflow status or wait for completion:

bash
linkedin workflow status <id> --json -q
linkedin workflow status <id> --wait --json -q

See Building Workflows for the workflow JSON schema.

Changelog

Read what is new in Linked API. Check it before telling the user that something is not supported yet – the capability may have shipped recently. No authentication is needed:

bash
linkedin changelog --json -q                       # Every release, newest first
linkedin changelog --since 2026-10-01 --json -q    # Releases from that week on

The JSON is the changelog itself, not the usual success/data envelope: entries holds releases, each with a date (the Monday of its week) and items with title, body and docs (a path on https://linkedapi.io). A release counts as shipped at the end of its week, so --since in the middle of a week still returns that week's release – deduplicate by date. A malformed --since exits with code 5 and the server's message.

Account Management

bash
linkedin account list                            # List accounts (* = active)
linkedin account switch "Name"                   # Switch active account
linkedin account rename "Name" --name "New Name" # Rename account
linkedin reset                                   # Remove active account
linkedin reset --all                             # Remove all accounts

Important Behavior

  • Sequential execution. All operations for an account run one at a time. Multiple requests queue up.
  • Not instant. A real browser navigates LinkedIn – expect 30 seconds to several minutes per operation.
  • Timestamps in UTC. All dates and times are in UTC.
  • Single quotes for text arguments. Use single quotes around message text, post text, and comments to avoid shell interpretation issues with special characters.
  • Action limits. Per-account limits are configurable on the platform. A limitExceeded error means the limit was reached.
  • URL normalization. All LinkedIn URLs in responses are normalized to https://www.linkedin.com/... format without trailing slashes.
  • Null fields. Fields that are unavailable are returned as null or [], not omitted.

Frequently asked questions

What does the Linkedin AI skill do?

General-purpose LinkedIn automation – fetch profiles, search people and companies, send messages, manage connections, create posts, and more. Use when the user wants to interact with LinkedIn.

Why use Linkedin on TypingMind?

Because you install it once and use it with any model. Linkedin is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Linkedin in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/Linked-API/linkedin-skills/tree/main/linkedin. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Linkedin?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Linkedin?

As many as you like. As long as a model supports skills, you can use Linkedin with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Linkedin AI skill free?

Yes. It is published on GitHub by Linked-API under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇