# LinkedIn API for agents

> API for Agents · https://apiforagents.dev/platforms/linkedin · HTML twin: https://apiforagents.dev/platforms/linkedin

People, companies, posts, jobs, comments, reactions and ads from LinkedIn.

Endpoint: `POST https://apiforagents.dev/v1/linkedin`. One op per call. Quote first with `"estimateOnly": true`.

## Prices (USD per record, pay as you go)

| Record | Per record |
|---|---|
| jobs | $0.001 |
| ads library | $0.002 |
| post comments | $0.002 |
| post reactions | $0.002 |
| posts | $0.002 |
| profile comments | $0.002 |
| profile reactions | $0.002 |
| companies | $0.004 |
| profiles | $0.004 |

## Operations

### profiles

Profile cards for up to ten people, by /in/<slug> vanity handle (a full profile URL is accepted and reduced to its slug). `include.posts` adds each person's recent posts to the same answer.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | /in/<slug> handles or profile URLs. |
| fields | no | list of enum | What each card carries: "profile" is the card itself (always), "positions" adds the person's work history. Omit for the card alone. Values: profile, positions. |
| include | no | object |  |
| include.posts | no | object |  |
| include.posts.limit | no | integer (1-50) | Recent posts to fetch per person, newest first; 1-50. |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| publicId | string |
| urn | string |
| name | string |
| firstName | string |
| lastName | string |
| headline | string |
| about | string |
| location | string |
| city | string |
| state | string |
| country | string |
| profileUrl | string |
| avatarUrl | string |
| coverUrl | string |
| followers | integer |
| connections | integer |
| isPremium | boolean |
| isOpenToWork | boolean |
| isHiring | boolean |
| isVerified | boolean |
| isCreator | boolean |
| isInfluencer | boolean |
| isOpenProfile | boolean |
| skills | list of string |
| companyName | string |
| positions | list of object |
| education | list of object |
| certifications | list of object |
| languages | list of object |
| projects | list of object |
| publications | list of object |
| courses | list of object |
| honors | list of object |
| volunteering | list of object |
| recommendations | list of object |
| causes | list of string |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"profiles","subjects":["satyanadella"]}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "publicId": "ananya-rao",
    "name": "Ananya Rao",
    "headline": "Head of Marketing at Paylane",
    "companyName": "Paylane",
    "location": "Bengaluru, Karnataka, India",
    "followers": 8421,
    "connections": 500,
    "isOpenToWork": false,
    "isHiring": true,
    "skills": [
      "Growth marketing",
      "B2B SaaS",
      "Brand strategy"
    ],
    "urn": "urn:li:fsd_profile:885327295",
    "avatarUrl": "https://img.linkedin.com/ananya-rao.jpg",
    "isPremium": false,
    "positions": [
      {
        "companyName": "Paylane",
        "title": "Head of Marketing",
        "startedOn": "2019-01",
        "isCurrent": true
      }
    ],
    "details": {}
  },
  {
    "publicId": "marcus-lee",
    "name": "Marcus Lee",
    "headline": "VP Sales, EMEA | B2B SaaS",
    "companyName": "Northfold",
    "location": "London, England, United Kingdom",
    "followers": 15230,
    "connections": 500,
    "isOpenToWork": false,
    "isHiring": false,
    "skills": [
      "Enterprise sales",
      "Negotiation",
      "Team leadership"
    ],
    "urn": "urn:li:fsd_profile:302922555",
    "avatarUrl": "https://img.linkedin.com/marcus-lee.jpg",
    "isPremium": false,
    "positions": [
      {
        "companyName": "Northfold",
        "title": "VP Sales",
        "startedOn": "2020-02",
        "isCurrent": true
      }
    ],
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=profiles (sign in first).

### posts

A person's recent posts with engagement. (Company-page posts are not served yet. Asking today is declined with a reason, never guessed at.)

| Field | Required | Type | Meaning |
|---|---|---|---|
| subject | yes | string (≤400 chars) | One /in/<slug> handle or profile URL. |
| limit | no | integer (1-50) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| urn | string |
| body | string |
| kind | string |
| postedAt | string |
| permalink | string |
| mediaUrl | string |
| mediaType | string |
| likes | integer |
| comments | integer |
| reposts | integer |
| author | object |
| mentions | list of object |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"posts","subject":"satyanadella","limit":10}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "author": {
      "handle": "ananya-rao",
      "type": "person"
    },
    "body": "We cut onboarding from 14 days to 3. Here is what changed, step by step.",
    "kind": "text",
    "postedAt": "2026-10-14T09:12:00Z",
    "likes": 1284,
    "comments": 96,
    "reposts": 41,
    "urn": "urn:li:activity:2164259024",
    "permalink": "https://www.linkedin.com/we-cut-onboarding-from-14-days-to-3-here-1000",
    "mediaUrl": "https://www.linkedin.com/we-cut-onboarding-from-14-days-to-3-here-1000",
    "details": {}
  },
  {
    "author": {
      "handle": "ananya-rao",
      "type": "person"
    },
    "body": "We're hiring two product marketers in Bengaluru. DM me.",
    "kind": "image",
    "postedAt": "2026-10-08T06:40:00Z",
    "likes": 412,
    "comments": 58,
    "reposts": 19,
    "urn": "urn:li:activity:2872631718",
    "permalink": "https://www.linkedin.com/we-re-hiring-two-product-marketers-in-be-1001",
    "mediaUrl": "https://www.linkedin.com/we-re-hiring-two-product-marketers-in-be-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=posts (sign in first).

### companies

Company pages for up to ten /company/<slug> handles or URLs.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | /company/<slug> handles or URLs. |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| universalName | string |
| urn | string |
| name | string |
| industry | string |
| sizeBucket | string |
| employeesCount | integer |
| followers | integer |
| website | string |
| linkedinUrl | string |
| hqLocation | string |
| hqStreet | string |
| hqCity | string |
| hqState | string |
| hqPostalCode | string |
| hqCountry | string |
| about | string |
| founded | integer |
| specialities | list of string |
| logoUrl | string |
| pageType | string |
| isVerified | boolean |
| isActive | boolean |
| jobsUrl | string |
| callToActionUrl | string |
| locations | list of object |
| employeesByLocation | list of object |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"companies","subjects":["microsoft"]}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "universalName": "paylane",
    "name": "Paylane",
    "industry": "Financial Services",
    "sizeBucket": "201-500",
    "employeesCount": 342,
    "followers": 48210,
    "website": "https://paylane.example",
    "hqLocation": "Bengaluru, Karnataka, India",
    "founded": 2017,
    "specialities": [
      "Payments",
      "Payouts",
      "APIs"
    ],
    "urn": "urn:li:fsd_company:70566685",
    "logoUrl": "https://img.linkedin.com/paylane.jpg",
    "details": {
      "tagline": "Payments for every shop",
      "employeesBySkill": [
        {
          "skill": "Sales",
          "count": 120
        },
        {
          "skill": "Python",
          "count": 85
        }
      ],
      "employeesByFunction": [
        {
          "function": "Engineering",
          "count": 210
        }
      ]
    }
  },
  {
    "universalName": "northfold",
    "name": "Northfold",
    "industry": "Software Development",
    "sizeBucket": "51-200",
    "employeesCount": 128,
    "followers": 15904,
    "website": "https://northfold.example",
    "hqLocation": "London, England, United Kingdom",
    "founded": 2019,
    "specialities": [
      "Finance automation",
      "Close management"
    ],
    "urn": "urn:li:fsd_company:1275972461",
    "logoUrl": "https://img.linkedin.com/northfold.jpg",
    "details": {
      "tagline": "Freight, simplified",
      "employeesBySkill": [
        {
          "skill": "Sales",
          "count": 90
        },
        {
          "skill": "Python",
          "count": 65
        }
      ],
      "employeesByFunction": [
        {
          "function": "Engineering",
          "count": 160
        }
      ]
    }
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=companies (sign in first).

### searchPeople

People search. With `company`: that company's people, filtered (employees-of-X). Without it: a GLOBAL search. Give `query` (e.g. "fintech founder") and/or titles. Find founders/leadership via titles (free text: "Founder", "CEO") and/or seniority bands (cxo, owner_partner); functions and tenure narrow further.

| Field | Required | Type | Meaning |
|---|---|---|---|
| company | no | string (≤400 chars) | A /company/<slug> handle or company URL: search only that company's people. Omit for a global search (then give query and/or titles). |
| query | no | string (≤300 chars) |  |
| titles | no | list of string | Current job titles, free text ("Founder", "Head of Marketing"); any match. |
| pastTitles | no | list of string | Titles the person held before, free text. Global search only. |
| pastCompanies | no | list of string | Company names the person worked at before. Global search only. |
| schools | no | list of string | School or university names the person attended. Global search only. |
| locations | no | list of string |  |
| industries | no | list of string | Leaf names or " > " paths. Validated against LinkedIn's 434-node taxonomy. |
| companySizes | no | list of enum | Headcount bands of the person's current employer: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+. Global search only. Values: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+. |
| seniority | no | list of enum | Seniority bands: cxo, owner_partner, vice_president, director, experienced_manager, entry_manager, strategic, senior, entry, in_training. Any match. Values: in_training, entry, senior, strategic, entry_manager, experienced_manager, director, vice_president, cxo, owner_partner. |
| functions | no | list of enum | Job functions: marketing, sales, engineering, finance, operations, product_management, human_resources … Any match. Values: accounting, administrative, arts_and_design, business_development, community_and_social_services, consulting, education, engineering, entrepreneurship, finance, healthcare_services, human_resources, information_technology, legal, marketing, media_and_communication, military_and_protective_services, operations, product_management, program_and_project_management, purchasing, quality_assurance, real_estate, research, sales. |
| yearsAtCompany | no | list of enum | Tenure at the current company, in bands: lt_1y, 1_2y, 3_5y, 6_10y, gt_10y. Values: lt_1y, 1_2y, 3_5y, 6_10y, gt_10y. |
| yearsOfExperience | no | list of enum | Total career length, the same bands as yearsAtCompany. Values: lt_1y, 1_2y, 3_5y, 6_10y, gt_10y. |
| recentlyChangedJobs | no | boolean | true: only people who started a new role recently. |
| recentlyPosted | no | boolean | true: only people who posted on LinkedIn recently. Global search only. |
| personNames | no | list of string | Person-name / current employer / HQ / language filters (global search honours all). |
| currentCompanies | no | list of string | Names of the person's current employer(s). Global search only. |
| companyHqLocations | no | list of string | Where the current employer is headquartered. Cities, regions or countries as written on LinkedIn ("Bengaluru", "United States"). |
| profileLanguages | no | list of string | Languages listed on the profile, by name ("English", "Hindi"). |
| limit | no | integer (1-50) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| publicId | string |
| urn | string |
| name | string |
| firstName | string |
| lastName | string |
| headline | string |
| about | string |
| location | string |
| city | string |
| state | string |
| country | string |
| profileUrl | string |
| avatarUrl | string |
| coverUrl | string |
| followers | integer |
| connections | integer |
| isPremium | boolean |
| isOpenToWork | boolean |
| isHiring | boolean |
| isVerified | boolean |
| isCreator | boolean |
| isInfluencer | boolean |
| isOpenProfile | boolean |
| skills | list of string |
| companyName | string |
| positions | list of object |
| education | list of object |
| certifications | list of object |
| languages | list of object |
| projects | list of object |
| publications | list of object |
| courses | list of object |
| honors | list of object |
| volunteering | list of object |
| recommendations | list of object |
| causes | list of string |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"searchPeople","company":"stripe","titles":["Head of Data"],"limit":10}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "publicId": "priya-nair",
    "name": "Priya Nair",
    "headline": "Head of Marketing · Ledgerly",
    "companyName": "Ledgerly",
    "location": "Bengaluru, Karnataka, India",
    "followers": 5120,
    "connections": 500,
    "isOpenToWork": false,
    "isHiring": false,
    "skills": [
      "Demand generation",
      "Fintech"
    ],
    "urn": "urn:li:fsd_profile:1103731855",
    "avatarUrl": "https://img.linkedin.com/priya-nair.jpg",
    "isPremium": false,
    "positions": [
      {
        "companyName": "Ledgerly",
        "title": "Head of Marketing",
        "startedOn": "2019-01",
        "isCurrent": true
      }
    ],
    "details": {}
  },
  {
    "publicId": "arjun-mehta",
    "name": "Arjun Mehta",
    "headline": "Marketing Director at Coinmint",
    "companyName": "Coinmint",
    "location": "Bengaluru, Karnataka, India",
    "followers": 3380,
    "connections": 500,
    "isOpenToWork": false,
    "isHiring": true,
    "skills": [
      "Performance marketing",
      "Payments"
    ],
    "urn": "urn:li:fsd_profile:1983785629",
    "avatarUrl": "https://img.linkedin.com/arjun-mehta.jpg",
    "isPremium": false,
    "positions": [
      {
        "companyName": "Coinmint",
        "title": "Marketing Director",
        "startedOn": "2020-02",
        "isCurrent": true
      }
    ],
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=searchPeople (sign in first).

### searchCompanies

Company search by keyword and structured filters.

| Field | Required | Type | Meaning |
|---|---|---|---|
| query | no | string (≤300 chars) |  |
| locations | no | list of string |  |
| companySizes | no | list of enum | Headcount bands: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+; any match. Values: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+. |
| industries | no | list of string | Industry names, leaf or " > " path, from LinkedIn's own taxonomy. |
| limit | no | integer (1-50) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| universalName | string |
| urn | string |
| name | string |
| industry | string |
| sizeBucket | string |
| employeesCount | integer |
| followers | integer |
| website | string |
| linkedinUrl | string |
| hqLocation | string |
| hqStreet | string |
| hqCity | string |
| hqState | string |
| hqPostalCode | string |
| hqCountry | string |
| about | string |
| founded | integer |
| specialities | list of string |
| logoUrl | string |
| pageType | string |
| isVerified | boolean |
| isActive | boolean |
| jobsUrl | string |
| callToActionUrl | string |
| locations | list of object |
| employeesByLocation | list of object |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"searchCompanies","query":"fintech","locations":["London"],"limit":10}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "universalName": "ledgerly",
    "name": "Ledgerly",
    "industry": "Software Development",
    "sizeBucket": "11-50",
    "employeesCount": 38,
    "followers": 4120,
    "website": "https://ledgerly.example",
    "hqLocation": "Berlin, Germany",
    "founded": 2021,
    "specialities": [
      "Accounting software",
      "SMBs"
    ],
    "urn": "urn:li:fsd_company:4164023981",
    "logoUrl": "https://img.linkedin.com/ledgerly.jpg",
    "details": {
      "tagline": "Payments for every shop"
    }
  },
  {
    "universalName": "coinmint",
    "name": "Coinmint",
    "industry": "Financial Services",
    "sizeBucket": "51-200",
    "employeesCount": 96,
    "followers": 12800,
    "website": "https://coinmint.example",
    "hqLocation": "Berlin, Germany",
    "founded": 2018,
    "specialities": [
      "Crypto custody"
    ],
    "urn": "urn:li:fsd_company:1700968753",
    "logoUrl": "https://img.linkedin.com/coinmint.jpg",
    "details": {
      "tagline": "Freight, simplified"
    }
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=searchCompanies (sign in first).

### jobs

Job listings search: `query` is the job-title anchor, the rest narrow it.

| Field | Required | Type | Meaning |
|---|---|---|---|
| query | yes | string (≤300 chars) |  |
| locations | no | list of string |  |
| companies | no | list of string | Hiring company names, as written on LinkedIn; any match. |
| industries | no | list of string | Industry names, leaf or " > " path, from LinkedIn's own taxonomy. |
| workplace | no | list of enum |  Values: remote, hybrid, onsite. |
| employmentType | no | list of enum |  Values: full_time, part_time, contract, internship, temporary. |
| experienceLevel | no | list of enum | Levels: internship, entry, associate, mid_senior, director, executive. Values: internship, entry, associate, mid_senior, director, executive. |
| postedWithin | no | enum |  Values: 1h, 1d, 7d, 30d. |
| salaryMin | no | integer (40-1000) | Thousands of USD a year, 40 and up; filtered in LinkedIn's $20k bands. |
| easyApply | no | boolean | true: only listings that take applications on LinkedIn itself. |
| under10Applicants | no | boolean | true: only listings with fewer than ten applicants so far. |
| sort | no | enum | Unset = the platform's default order. Values: relevance, newest. |
| limit | no | integer (1-50) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| jobId | string |
| title | string |
| companyName | string |
| location | string |
| city | string |
| state | string |
| country | string |
| employmentType | string |
| workplaceType | string |
| isRemoteAllowed | boolean |
| experienceLevel | string |
| industries | list of string |
| functions | list of string |
| salaryText | string |
| listedAt | string |
| expiresAt | string |
| applicants | integer |
| url | string |
| applyUrl | string |
| applicantTrackingSystem | string |
| description | string |
| descriptionHtml | string |
| companyUrn | string |
| companySlug | string |
| companyUrl | string |
| companyLogoUrl | string |
| companyWebsite | string |
| companyDescription | string |
| companyEmployees | integer |
| companyFollowers | integer |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"jobs","query":"data engineer","locations":["Berlin"],"postedWithin":"7d","limit":10}'
```

Example response rows (real rows, business data; a live row carries every field above):

```json
[
  {
    "jobId": "4430707116",
    "title": "Product Manager (Manufacturing) - Hybrid",
    "companyName": "MacLean Power Systems",
    "location": "Manteca, California, United States",
    "employmentType": "full_time",
    "listedAt": "2026-08-22T15:42:18+00:00",
    "applyUrl": "https://jobs.dayforcehcm.com/en-US/mlp/CANDIDATEPORTAL/jobs/15691?src=LinkedIn",
    "description": "MPS in Stockton, CA is seeking a talented Product Manager (Overhead High Voltage Switchgear). In this role you will be responsible for managing product portfolios, providing technical and commercial support to customers, and developing strategic and tactical plans encompassing the market and competitive analysis for our Stockton facility.\n\nThis role is Hybrid 3-2, and our facility is located in Stockton, CA.\n\nWhat You’ll Do\n\nOversee the implementation of technical product solutions for clients a",
    "details": {}
  },
  {
    "jobId": "4419567749",
    "title": "Sr. Engineering and Product Manager",
    "companyName": "Justrite Safety Group",
    "location": "Broomfield, Colorado, United States",
    "employmentType": "full_time",
    "listedAt": "2026-08-22T15:22:45+00:00",
    "applyUrl": "https://recruiting2.ultipro.com/JUS1001JUSTM/JobBoard/2d5c8dc9-71e2-46d7-aa3d-305883f6102b/OpportunityDetail?opportunityId=12d54091-fc20-4284-8485-92c704543815&source=LinkedIn",
    "description": "About Justrite Safety Group\n\nAt Justrite Safety Group, we're more than just a collection of industrial safety companies; we're a dynamic organization dedicated to protecting people, property, and the planet. Our ever-growing portfolio of companies collaborates to deliver advanced industrial safety solutions that set the standard for excellence.\n\nAs our business continues to grow, we continue to look for top talent to join our team as we lead the charge in revolutionizing industrial safety, ensur",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=jobs (sign in first).

### searchPosts

Search LinkedIn POSTS by keyword. The content itself, not people or companies. `query` is the search ("layoffs fintech", a product name, a hashtag). Narrow by who is mentioned, the content type (videos, images, documents…), how recent, and sort by relevance or date.

| Field | Required | Type | Meaning |
|---|---|---|---|
| query | yes | string (≤300 chars) | Words the posts must contain. Always needed, even with mentioning (a mention-only ask is refused, verified 2026-09-23): to list all that tags a company or person, use their name as the query. |
| mentioning | no | list of string | Only posts that tag these people or companies: /in/<slug> or /company/<slug> handles, or their URLs. |
| contentType | no | enum | What kind of post: videos, images, jobs, live_videos, documents, collaborative_articles. Omit or "all" for every kind. Values: all, videos, images, jobs, live_videos, documents, collaborative_articles. |
| postedWithin | no | enum |  Values: any, 1h, 1d, 7d, 30d, 3m, 6m, 1y. |
| sort | no | enum |  Values: relevance, newest. |
| includeReposts | no | boolean | true: reposts of other people's posts count as hits too. |
| includeQuotePosts | no | boolean | true: posts that quote another post count as hits too. |
| limit | no | integer (1-50) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| urn | string |
| body | string |
| kind | string |
| postedAt | string |
| permalink | string |
| mediaUrl | string |
| mediaType | string |
| likes | integer |
| comments | integer |
| reposts | integer |
| author | object |
| mentions | list of object |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"searchPosts","query":"AI agents","postedWithin":"7d","limit":10}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "author": {
      "handle": "marcus-lee",
      "type": "person"
    },
    "body": "Layoffs in fintech this quarter: what I'm hearing from 40 sales leaders.",
    "kind": "text",
    "postedAt": "2026-10-15T08:00:00Z",
    "likes": 3120,
    "comments": 402,
    "reposts": 210,
    "urn": "urn:li:activity:31086471",
    "permalink": "https://www.linkedin.com/layoffs-in-fintech-this-quarter-what-i-m-1000",
    "mediaUrl": "https://www.linkedin.com/layoffs-in-fintech-this-quarter-what-i-m-1000",
    "details": {}
  },
  {
    "author": {
      "handle": "leila-haddad",
      "type": "person"
    },
    "body": "If you were part of the fintech layoffs, I'm sharing 25 open roles below.",
    "kind": "text",
    "postedAt": "2026-10-13T15:30:00Z",
    "likes": 1840,
    "comments": 233,
    "reposts": 512,
    "urn": "urn:li:activity:3331202746",
    "permalink": "https://www.linkedin.com/if-you-were-part-of-the-fintech-layoffs--1001",
    "mediaUrl": "https://www.linkedin.com/if-you-were-part-of-the-fintech-layoffs--1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=searchPosts (sign in first).

### postComments

Comments on up to ten LinkedIn POSTS, by post URL. `includeReplies` pulls nested replies; `postedWithin` limits how far back to read.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | Post URLs. |
| includeReplies | no | boolean | true: nested replies come back under their parent comment, not only top-level comments. |
| postedWithin | no | enum |  Values: any, 1d, 7d, 30d. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| commentId | string |
| commentUrl | string |
| postUrl | string |
| postUrn | string |
| commenterProfileId | string |
| commenterHandle | string |
| commenterName | string |
| commenterHeadline | string |
| commenterUrl | string |
| commenterAvatarUrl | string |
| commenterType | string |
| commenterFollowers | integer |
| isAuthor | boolean |
| edited | boolean |
| likes | integer |
| replies | integer |
| reactions | list of object |
| body | string |
| commentedAt | string |
| mentions | list of string |
| postAuthor | string |
| postAuthorHandle | string |
| postAuthorUrl | string |
| postAuthorHeadline | string |
| postAuthorAvatarUrl | string |
| postAuthorProfileId | string |
| postAuthorType | string |
| postText | string |
| postPostedAt | string |
| postMediaUrl | string |
| postLikes | integer |
| postComments | integer |
| postReposts | integer |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"postComments","subjects":["https://www.linkedin.com/posts/<post-id>"],"limit":25}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "commenterHandle": "priya-nair",
    "commenterName": "Priya Nair",
    "commenterHeadline": "Product Lead at Ledgerly",
    "body": "This matches what we saw. Did churn move too?",
    "likes": 34,
    "replies": 3,
    "commentedAt": "2026-10-14T10:02:00Z",
    "postAuthor": "Ananya Rao",
    "isAuthor": false,
    "commentId": "3095264851",
    "commentUrl": "https://www.linkedin.com/priya-nair-1000",
    "postUrl": "https://www.linkedin.com/priya-nair-1000",
    "postUrn": "urn:li:activity:1393902121",
    "commenterProfileId": "3708772264",
    "commenterUrl": "https://www.linkedin.com/priya-nair-1000",
    "postAuthorUrl": "https://www.linkedin.com/priya-nair-1000",
    "details": {}
  },
  {
    "commenterHandle": "tom-becker",
    "commenterName": "Tom Becker",
    "commenterHeadline": "Founder, Brightdesk",
    "body": "Saving this for our next planning week.",
    "likes": 12,
    "replies": 0,
    "commentedAt": "2026-10-14T10:40:00Z",
    "postAuthor": "Ananya Rao",
    "isAuthor": false,
    "commentId": "2364499118",
    "commentUrl": "https://www.linkedin.com/tom-becker-1001",
    "postUrl": "https://www.linkedin.com/tom-becker-1001",
    "postUrn": "urn:li:activity:492950413",
    "commenterProfileId": "1378818087",
    "commenterUrl": "https://www.linkedin.com/tom-becker-1001",
    "postAuthorUrl": "https://www.linkedin.com/tom-becker-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=postComments (sign in first).

### profileComments

A profile's OWN commenting activity. The comments up to ten people left across LinkedIn, by /in/<slug> handle, newest first.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | /in/<slug> handles or profile URLs. |
| postedWithin | no | enum |  Values: any, 1d, 7d, 30d. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| commentId | string |
| commentUrl | string |
| postUrl | string |
| postUrn | string |
| commenterProfileId | string |
| commenterHandle | string |
| commenterName | string |
| commenterHeadline | string |
| commenterUrl | string |
| commenterAvatarUrl | string |
| commenterType | string |
| commenterFollowers | integer |
| isAuthor | boolean |
| edited | boolean |
| likes | integer |
| replies | integer |
| reactions | list of object |
| body | string |
| commentedAt | string |
| mentions | list of string |
| postAuthor | string |
| postAuthorHandle | string |
| postAuthorUrl | string |
| postAuthorHeadline | string |
| postAuthorAvatarUrl | string |
| postAuthorProfileId | string |
| postAuthorType | string |
| postText | string |
| postPostedAt | string |
| postMediaUrl | string |
| postLikes | integer |
| postComments | integer |
| postReposts | integer |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"profileComments","subjects":["satyanadella"],"limit":25}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "commenterHandle": "marcus-lee",
    "commenterName": "Marcus Lee",
    "commenterHeadline": "VP Sales, EMEA | B2B SaaS",
    "body": "Strong take. Discovery calls are where most deals are lost.",
    "likes": 48,
    "replies": 5,
    "commentedAt": "2026-10-15T07:30:00Z",
    "postAuthor": "Emma Novak",
    "isAuthor": false,
    "commentId": "3190665176",
    "commentUrl": "https://www.linkedin.com/marcus-lee-1000",
    "postUrl": "https://www.linkedin.com/marcus-lee-1000",
    "postUrn": "urn:li:activity:1646120582",
    "commenterProfileId": "1150986638",
    "commenterUrl": "https://www.linkedin.com/marcus-lee-1000",
    "postAuthorUrl": "https://www.linkedin.com/marcus-lee-1000",
    "details": {}
  },
  {
    "commenterHandle": "marcus-lee",
    "commenterName": "Marcus Lee",
    "commenterHeadline": "VP Sales, EMEA | B2B SaaS",
    "body": "Congrats on the launch, team!",
    "likes": 9,
    "replies": 1,
    "commentedAt": "2026-10-12T16:05:00Z",
    "postAuthor": "Daniel Kim",
    "isAuthor": false,
    "commentId": "4239718143",
    "commentUrl": "https://www.linkedin.com/marcus-lee-1001",
    "postUrl": "https://www.linkedin.com/marcus-lee-1001",
    "postUrn": "urn:li:activity:3776163747",
    "commenterProfileId": "3190281601",
    "commenterUrl": "https://www.linkedin.com/marcus-lee-1001",
    "postAuthorUrl": "https://www.linkedin.com/marcus-lee-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=profileComments (sign in first).

### postReactions

Reactions on up to ten LinkedIn POSTS, by post URL. Who reacted and how. `reactionTypes` filters to specific reactions (Like, Celebrate…).

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | Post URLs. |
| reactionTypes | no | list of enum | Keep only these reactions: like, celebrate, support, love, insightful, funny. Omit for all of them. Values: like, celebrate, support, love, insightful, funny. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| reactorProfileId | string |
| reactorHandle | string |
| reactorName | string |
| reactorHeadline | string |
| reactorUrl | string |
| reactorAvatarUrl | string |
| reactorLocation | string |
| reactionType | string |
| postUrn | string |
| postUrl | string |
| postAuthor | string |
| postAuthorHandle | string |
| postAuthorUrl | string |
| postAuthorHeadline | string |
| postAuthorProfileId | string |
| postAuthorType | string |
| postText | string |
| postPostedAt | string |
| postMediaUrl | string |
| postLikes | integer |
| postComments | integer |
| postReposts | integer |
| reactedAt | string |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"postReactions","subjects":["https://www.linkedin.com/posts/<post-id>"],"reactionTypes":["like"],"limit":25}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "reactorHandle": "priya-nair",
    "reactorName": "Priya Nair",
    "reactorHeadline": "Product Lead at Ledgerly",
    "reactorLocation": "Mumbai, India",
    "reactionType": "LIKE",
    "postAuthor": "Ananya Rao",
    "reactedAt": "2026-10-14T09:30:00Z",
    "reactorProfileId": "4155200177",
    "reactorUrl": "https://www.linkedin.com/priya-nair-1000",
    "postUrn": "urn:li:activity:492783029",
    "postUrl": "https://www.linkedin.com/priya-nair-1000",
    "postAuthorUrl": "https://www.linkedin.com/priya-nair-1000",
    "details": {}
  },
  {
    "reactorHandle": "daniel-kim",
    "reactorName": "Daniel Kim",
    "reactorHeadline": "Engineering Manager at Kitebank",
    "reactorLocation": "Seoul, South Korea",
    "reactionType": "PRAISE",
    "postAuthor": "Ananya Rao",
    "reactedAt": "2026-10-14T09:41:00Z",
    "reactorProfileId": "1968241913",
    "reactorUrl": "https://www.linkedin.com/daniel-kim-1001",
    "postUrn": "urn:li:activity:3363527946",
    "postUrl": "https://www.linkedin.com/daniel-kim-1001",
    "postAuthorUrl": "https://www.linkedin.com/daniel-kim-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=postReactions (sign in first).

### profileReactions

A profile's OWN reactions. What up to ten people reacted to across LinkedIn, by /in/<slug> handle, newest first.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | /in/<slug> handles or profile URLs. |
| postedWithin | no | enum |  Values: any, 1d, 7d, 30d. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| reactorProfileId | string |
| reactorHandle | string |
| reactorName | string |
| reactorHeadline | string |
| reactorUrl | string |
| reactorAvatarUrl | string |
| reactorLocation | string |
| reactionType | string |
| postUrn | string |
| postUrl | string |
| postAuthor | string |
| postAuthorHandle | string |
| postAuthorUrl | string |
| postAuthorHeadline | string |
| postAuthorProfileId | string |
| postAuthorType | string |
| postText | string |
| postPostedAt | string |
| postMediaUrl | string |
| postLikes | integer |
| postComments | integer |
| postReposts | integer |
| reactedAt | string |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"profileReactions","subjects":["satyanadella"],"limit":25}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "reactorHandle": "sofia-ortiz",
    "reactorName": "Sofia Ortiz",
    "reactorHeadline": "Data Engineer · Python, dbt, Airflow",
    "reactorLocation": "Austin, Texas, United States",
    "reactionType": "LIKE",
    "postAuthor": "Tom Becker",
    "postText": "We open-sourced our data quality checks.",
    "reactedAt": "2026-10-15T14:10:00Z",
    "reactorProfileId": "3680798353",
    "reactorUrl": "https://www.linkedin.com/sofia-ortiz-1000",
    "postUrn": "urn:li:activity:3845499993",
    "postUrl": "https://www.linkedin.com/sofia-ortiz-1000",
    "postAuthorUrl": "https://www.linkedin.com/sofia-ortiz-1000",
    "details": {}
  },
  {
    "reactorHandle": "sofia-ortiz",
    "reactorName": "Sofia Ortiz",
    "reactorHeadline": "Data Engineer · Python, dbt, Airflow",
    "reactorLocation": "Austin, Texas, United States",
    "reactionType": "EMPATHY",
    "postAuthor": "Leila Haddad",
    "postText": "Today is my last day at Coinmint.",
    "reactedAt": "2026-10-12T18:22:00Z",
    "reactorProfileId": "3776001972",
    "reactorUrl": "https://www.linkedin.com/sofia-ortiz-1001",
    "postUrn": "urn:li:activity:1372690733",
    "postUrl": "https://www.linkedin.com/sofia-ortiz-1001",
    "postAuthorUrl": "https://www.linkedin.com/sofia-ortiz-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=profileReactions (sign in first).

### adsLibrary

Ads from the LinkedIn Ad Library, by Ad Library URL. An advertiser's page (all their live ads) or a single ad's detail URL.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subject | yes | string (≤400 chars) | An Ad Library URL. An advertiser page or one ad's detail page. |
| limit | no | integer (1-100) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| adId | string |
| adUrl | string |
| advertiserUrl | string |
| paidBy | string |
| headline | string |
| body | string |
| format | string |
| mediaType | string |
| mediaUrl | string |
| clickUrl | string |
| impressions | integer |
| targetingLocation | string |
| started | string |
| ended | string |
| daysActive | integer |
| details | object |

`details` is always the last field: everything else the source sent for that row, under our own field names. Its keys depend on the source that answered, so read them defensively; it is `{}` when there is nothing more.

Example request:

```bash
curl -X POST https://apiforagents.dev/v1/linkedin \
  -H "Authorization: Bearer $AFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"adsLibrary","subject":"https://www.linkedin.com/ad-library/search?companyIds=<company-id>","limit":10}'
```

Example response rows (made-up names, real field names; a live row carries every field above):

```json
[
  {
    "paidBy": "Northfold",
    "headline": "Close your books 3x faster",
    "body": "Finance teams at 400+ companies close in 2 days.",
    "format": "SINGLE_IMAGE",
    "mediaType": "image",
    "impressions": "10k-50k",
    "targetingLocation": "United Kingdom",
    "started": "2026-09-02",
    "daysActive": 44,
    "adId": "3114963231",
    "adUrl": "https://www.linkedin.com/finance-teams-at-400-companies-close-in--1000",
    "advertiserUrl": "https://www.linkedin.com/finance-teams-at-400-companies-close-in--1000",
    "mediaUrl": "https://www.linkedin.com/finance-teams-at-400-companies-close-in--1000",
    "clickUrl": "https://www.linkedin.com/finance-teams-at-400-companies-close-in--1000",
    "details": {}
  },
  {
    "paidBy": "Northfold",
    "headline": "The 2026 finance team benchmark",
    "body": "Download the report: 1,200 teams surveyed.",
    "format": "DOCUMENT",
    "mediaType": "document",
    "impressions": "50k-100k",
    "targetingLocation": "Europe",
    "started": "2026-09-20",
    "daysActive": 26,
    "adId": "3288908810",
    "adUrl": "https://www.linkedin.com/download-the-report-1-200-teams-surveyed-1001",
    "advertiserUrl": "https://www.linkedin.com/download-the-report-1-200-teams-surveyed-1001",
    "mediaUrl": "https://www.linkedin.com/download-the-report-1-200-teams-surveyed-1001",
    "clickUrl": "https://www.linkedin.com/download-the-report-1-200-teams-surveyed-1001",
    "details": {}
  }
]
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=adsLibrary (sign in first).

### history (free)

The stored time series. Free, reads what captures already wrote.

| Field | Required | Type | Meaning |
|---|---|---|---|
| subjects | yes | list of string (1-10 items) | Handles or URLs of the chosen entity kind. |
| entity | no | enum | Whose series: "people" (/in/ handles) or "companies" (/company/ handles). Values: people, companies. |
| metric | no | string | people: followers | connections; companies: followers | employees_count |
| days | no | integer (1-730) |  |

Response fields (each row of data; every field present, null when the source had nothing):

| Field | Type |
|---|---|
| subject |  |
| metric |  |
| points[].date |  |
| points[].value |  |

Request shape:

```json
{
  "op": "history",
  "subjects": [
    "example"
  ]
}
```

Try it in the playground: https://apiforagents.dev/dashboard/run?platform=linkedin&op=history (sign in first).

## Notes for the agent

Measured LinkedIn data, one operation per call. /in/ handles come from evidence (web search, a pasted URL, a prior answer). Never typed from a name. A `publicId` of the form ACoAA…/ ACwAA… is LinkedIn's member id, which some search rows carry instead of a handle: it works for profiles here, but contacts needs the /in/ handle. Web-search the person for it. Never typed from a name: first-last slugs often name a DIFFERENT person, and the fetch bills. ops: profiles (batch of /in/ handles or URLs; fields=["positions"] adds the work history, include.posts adds each person's recent posts in the same call), posts (one person, deep. Includes the author's profile card when held), companies (company pages), searchPeople (a company's people filtered by title/seniority/function, or GLOBAL with query and no company), searchCompanies (query + size/industry/ location), jobs (listings by title + filters), searchPosts (find POSTS by keyword. The content itself, not people/companies; narrow by mention, content type, recency), postComments (a post's comment thread by URL), profileComments (a person's OWN commenting activity by /in/ handle), postReactions (who reacted to a post, filterable by reaction), profileReactions (what a person reacted to), adsLibrary (an advertiser's public ads from an Ad Library URL), history (stored series, free). A person's work email and mobile number are the `contacts` tool's job. Find the /in/ here first. Ops are independent. Issue several as PARALLEL tool calls for faster answers.
