Bowmark AIdocs

LinkedIn

The professional network — people, employers, jobs, posts and LinkedIn Learning.

The professional network — people, employers, jobs, posts and LinkedIn Learning. Three surfaces are callable: reading one member's public profile, searching the public job board, and reading a single posting in full.

Domain: linkedin.com

Also known as: LinkedIn, linkedin.com, LinkedIn Corporation, LinkedIn Learning, Lynda.com

Call it directly

bowmark.providers.linkedin.searchJobs(query: LinkedinJobSearchQuery | string): Promise<LinkedinJobSearchResult[]>
bowmark.providers.linkedin.getCompany(urlOrHandle: string): Promise<LinkedinCompany>
bowmark.providers.linkedin.getJob(url: string): Promise<LinkedinJobPosting>
bowmark.providers.linkedin.getProfile(urlOrSlug: string): Promise<LinkedinProfile>
bowmark.providers.linkedin.searchPeople(query: string | {query: string, limit?: number}): Promise<LinkedinPeopleSearch>

Functions

FunctionWhat it does
searchJobsSearches LinkedIn's public job board and returns matching postings — title, employer and employer page, location, and a real ISO posting date — each with the id that getJob takes, so a…
getCompanyReads one company's public LinkedIn page — name, tagline, the self-written description, industry, headcount band, headquarters, company type, founding year, specialties, website and logo.
getJobReads one job posting in full from its URL — title, employer, location, the whole description, and LinkedIn's four job criteria (seniority, employment type, job function, industries). Takes…
getProfileReads one member's public LinkedIn profile — name, headline, location, current title and employer, full position history, education, and past organisations (board seats, prior employers…
searchPeopleFinds LinkedIn members by NAME and returns each match's full public profile — the same shape getProfile returns, in full, not a snippet.

Types

interface LinkedinJobSearchResult {
  id: string;                  // the posting id — pass it straight to getJob
  url: string;
  title: string;
  company: string | null;
  companyUrl: string | null;
  location: string | null;
  postedDate: string | null;   // a real ISO date, e.g. "2026-07-28"
  isNew: boolean;
  hiringFlag: string | null;   // e.g. "Actively Hiring", where the card shows one
}

interface LinkedinJobSearchQuery {
  keywords?: string;
  location?: string;
  geoId?: string;              // LinkedIn's numeric region id, where a place name is ambiguous
  postedWithin?: "24h" | "week" | "month";
  limit?: number;              // default 10, capped at 1000
}

interface LinkedinJobPosting {
  id: string;
  url: string;
  title: string;
  company: string | null;
  companyUrl: string | null;
  location: string | null;
  description: string;
  descriptionHtml: string;
  seniority: string | null;
  employmentType: string | null;
  jobFunction: string | null;
  industries: string | null;
  postedRelative: string | null;  // the site's own phrase, e.g. "2 days ago"
  applicants: string | null;      // bucketed, e.g. "Over 200 applicants"
  salaryRange: string | null;     // only where the employer published one
  closed: boolean;
}

interface LinkedinPeopleSearch {
  profiles: LinkedinProfile[];
  // One line per candidate the index found and getProfile could NOT read. Empty
  // on a clean search. A short `profiles` with an empty `warnings` means the
  // index knew of that many people; a short one with warnings means some
  // refused us — read this before treating the list as everyone by that name.
  warnings: string[];
}

interface LinkedinProfile {
  id: string;                  // the URL slug, e.g. "williamhgates"
  url: string;
  name: string;
  headline: string | null;     // the member's own one-liner
  badge: string | null;        // a status badge ("Creator", "Top Voice"), where the member has one
  location: string | null;
  country: string | null;      // ISO 3166 alpha-2, e.g. "US"
  photoUrl: string | null;
  followers: number | null;
  currentTitle: string | null;
  currentEmployer: string | null;
  currentEmployerUrl: string | null;
  positions: LinkedinProfilePosition[];    // every position, newest first
  education: LinkedinProfileSchool[];      // schools only
  pastOrganizations: LinkedinProfileSchool[]; // past employers and board seats, not schools
  languages: string[];
}

interface LinkedinProfilePosition {
  title: string | null;
  company: string | null;
  companyUrl: string | null;   // feeds straight into getCompany
  location: string | null;
  startDate: string | null;    // "2000" or "2014-02" — LinkedIn publishes both granularities
  endDate: string | null;
}

interface LinkedinProfileSchool {
  name: string;
  url: string | null;
  startDate: string | null;
  endDate: string | null;
}

interface LinkedinCompany {
  id: string;                  // the URL handle, e.g. "microsoft" — what getCompany takes
  url: string;
  name: string;
  tagline: string | null;      // the one-line pitch under the name
  description: string | null;  // the company's own "About us" prose, newlines preserved
  website: string | null;      // whatever the company linked, not always its front door
  industry: string | null;     // ONE value — LinkedIn lets a company pick exactly one
  companySize: string | null;  // the site's own BAND, e.g. "10,001+ employees"
  employeesOnLinkedin: number | null; // MEMBERS claiming this employer — not a headcount
  headquarters: string | null; // as displayed, e.g. "Redmond, Washington"
  address: LinkedinCompanyAddress | null; // the ld+json block, where one was published
  organizationType: string | null; // "Public Company", "Privately Held", "Nonprofit"
  foundedYear: number | null;
  specialties: string[];       // LinkedIn publishes ONE comma-joined string; this is it split
  logoUrl: string | null;
}

interface LinkedinCompanyAddress {
  streetAddress: string | null;
  addressLocality: string | null;
  addressRegion: string | null;
  postalCode: string | null;
  addressCountry: string | null;
}