Blog/Developer Tools/

LinkedIn Company Research API Tutorial | SandBase

Build a LinkedIn company-research workflow: read a company profile, pull its posts, and page the feed — one SandBase key, no LinkedIn login, no SDK.

Dark cinematic render of a LinkedIn company profile resolving into a feed of company posts, feeding an agent core

If you do B2B research or competitive intelligence, LinkedIn company pages are a rich, structured source: headcount, headquarters, follower base, and a public post feed. This LinkedIn Company Research API tutorial wires a repeatable loop with two SandBase endpoints — read the company profile, then pull its posts — so an agent can run it end to end. It builds on the LinkedIn public data API hub; read that first for the big picture.

Everything here is public, read-only data. There is no LinkedIn login and no SDK — a SandBase API key is still required to authenticate. The endpoint API reference is the source of truth for parameters and the response envelope. The reference guarantees only that envelope; the payload field names below come from calls I ran (tested on 2026-09-28, UTC) and are illustrative, observed-only — not documented guarantees — so confirm them against a live response.

Key takeaway

  • Two endpoints form the loop: company-profile (firmographics) → company-posts (public feed).
  • Each call is POST /v1/api/linkedin/web-v2/<path> with a company url, one SANDBASE_API_KEY.
  • Both endpoints take the same company url, so the loop is trivially chainable.
  • Public, read-only data only — no posting, no private/account-only data.

SandBase vs. the official LinkedIn API

Your needUse
Public, read-only company profiles and postsSandBase LinkedIn public-data API
Manage a page, post, or use Marketing/partner APIsLinkedIn’s official APIs
Private or member-only dataNeither public workflow

The workflow at a glance

  1. Read the profile with linkedin/web-v2/company-profile using a company url.
  2. Pull the posts with linkedin/web-v2/company-posts using the same url, paging with the returned paging.

Each endpoint returns the shared envelope — an id, a status, the model, and the payload on a completed run.

SandBase LinkedIn API page with the endpoints used in this workflow The LinkedIn endpoints on SandBase — company-profile and company-posts drive this loop.

Step 0: one helper for every call

import os
import requests

API = "https://api.sandbase.ai/v1/api"
HEADERS = {
    "Authorization": f"Bearer {os.environ['SANDBASE_API_KEY']}",
    "Content-Type": "application/json",
}

def call(path: str, payload: dict) -> dict:
    resp = requests.post(f"{API}/{path}", headers=HEADERS, json=payload, timeout=70)
    resp.raise_for_status()
    body = resp.json()
    if body.get("status") != "completed":
        raise RuntimeError(body.get("error", {}).get("message", f"{path} did not complete"))
    # Envelope can vary: prefer a top-level `output`, else `outputs[0].data`.
    output = body.get("output")
    if output is None and body.get("outputs"):
        output = body["outputs"][0].get("data", {})
    return output or {}

Step 1: read the company profile

url = "https://www.linkedin.com/company/openai"
profile = call("linkedin/web-v2/company-profile", {"url": url})
print(profile.get("company_size"), "|", profile.get("followers"), "followers")
print("HQ:", profile.get("headquarters"))

In the response I captured (company-profile run id 79201745-d83f-4b1f-bee3-ba676cd1a1f0, tested on 2026-09-28, UTC), the payload carried about, description, company_size, followers, employees, and headquarters — illustrative, observed-only fields. Read each with .get() and confirm against a live response.

SandBase API reference for the LinkedIn company-profile endpoint The company-profile reference — the source of truth for the url parameter and response path.

Step 2: pull the company posts

feed = call("linkedin/web-v2/company-posts", {"url": url})
posts = feed.get("data", [])
paging = feed.get("paging")
for p in posts[:5]:
    print(p.get("num_likes"), "likes,", p.get("num_comments"), "comments -", p.get("posted"))

In my run (company-posts run id acda947a-5c3e-4114-a762-b1474e333bff), the payload carried a data list of posts (each with num_likes, num_comments, num_reposts, posted, and poster) plus a paging object. To page, follow the paging object per the reference — confirm the exact mechanism against it.

SandBase API reference for the LinkedIn company-posts endpoint The company-posts reference — pass the same company url; page via the paging object.

Putting it together

def research(company_url: str):
    profile = call("linkedin/web-v2/company-profile", {"url": company_url})
    feed = call("linkedin/web-v2/company-posts", {"url": company_url})
    posts = feed.get("data", [])
    engagement = [
        {"posted": p.get("posted"), "likes": p.get("num_likes"), "comments": p.get("num_comments")}
        for p in posts if isinstance(p, dict)
    ]
    return {
        "company_size": profile.get("company_size"),
        "followers": profile.get("followers"),
        "recent_posts": engagement,
    }

Because both endpoints take the same company url and share the same envelope, the loop stays flat: one status check in call(...) and one .get() pattern across profile and posts.

Common use cases

Competitive intelligence

Read a competitor’s company_size, followers, and headquarters, then pull recent posts to see what they promote and how it lands (likes, comments, reposts). Input: a company url. Output: firmographics plus a post-engagement sample. Endpoints: company-profile, company-posts.

Lead and account research

Enrich a target-account list with company_size and followers from company-profile to prioritize outreach. Input: company urls. Output: comparable firmographics. Endpoint: company-profile.

Content and messaging analysis

Pull a company’s posts and analyze poster, cadence, and engagement to understand their content strategy. Input: a company url. Output: a post feed with engagement. Endpoint: company-posts.

Hiring and growth signals

A company’s company_size and followers over successive reads, combined with the themes and frequency of its recent posts, hint at momentum — a company posting heavily about hiring or product launches alongside follower growth is likely scaling. Poll the two endpoints on a cadence, store the numbers, and compare across runs. Read every field defensively and treat the trend as a directional signal, since observed fields vary. Input: a company url. Output: firmographic and posting trends over time. Endpoints: company-profile, company-posts.

Practical notes

  • Envelope can vary. The reference documents outputs[0].data; read either shape (prefer output, fall back to outputs[0].data).
  • Page via the paging object. Follow the reference’s paging mechanism for company-posts.
  • Business fields are observed-only. Treat followers, num_likes, company_size, and the like as observed and confirm live.
  • Public, read-only data only. No posting, no member-only data. Authenticate with a SandBase API key.
  • Be a good client. Retry with backoff on transient errors such as HTTP 429; page rather than hammering.

FAQ

Do I need a LinkedIn developer app or login? No. You authenticate to SandBase with your SANDBASE_API_KEY. These read endpoints need no LinkedIn account or OAuth on your side.

What identifies a company? A company page url (e.g. https://www.linkedin.com/company/<slug>). Both endpoints take the same url.

How do I page through more posts? The company-posts payload carries a paging object; follow it per the reference.

Can I read member profiles or private data? This tutorial covers company endpoints. The hub also documents public person-profile reads; private and member-only data are out of scope.

Wrap up

Two endpoints, one envelope, one company url — that is the whole company-research loop. For the full endpoint catalog, see the LinkedIn public data API hub. When you are ready: