Blog/Tutorials

How to post to LinkedIn via API in TypeScript

June 5, 2026·7 min readTutorials

Step-by-step guide to posting text updates, articles, and images to LinkedIn Company Pages and personal profiles via API — including partner token setup and content type rules.

LinkedIn's API requires partner-level access for most publishing features — but Aether is already approved. You get LinkedIn posting without the 6-month review process. Here's how to go from zero to publishing in under an hour.

Prerequisites

  • An Aether account — free tier supports 3 connected accounts
  • A LinkedIn Company Page (for Page posts) or a personal LinkedIn account
  • Node.js 18+ in your project

1. Install the SDK

npm install aether

2. Connect a LinkedIn account

Aether supports two LinkedIn profile types: personal profiles ( type: "person") and Company Pages (type: "page"). Use platform: "linkedin" for both — the OAuth flow lets the user choose which pages to grant access to.

import Aether from "aether";

const aether = new Aether({ apiKey: process.env.AETHER_API_KEY });

// Generate an OAuth link — choose "linkedin" for personal profiles
// or "linkedin_page" for Company Pages
const link = await aether.connectLinks.create({
  platform: "linkedin",
  redirectUrl: "https://yourapp.com/oauth/linkedin/callback",
});

// Redirect your user to link.url
console.log(link.url);

LinkedIn tokens expire after 60 days. Aether's token-refresh worker proactively renews them 24 hours before expiry — your users won't need to reconnect.

3. List connected profiles

// List all connected LinkedIn profiles
const profiles = await aether.profiles.list({ platform: "linkedin" });

// profiles.data looks like:
// [
//   { id: "li_abc123", displayName: "Acme Corp", type: "page" },
//   { id: "li_xyz789", displayName: "Jane Smith", type: "person" }
// ]

const pageId   = profiles.data.find(p => p.type === "page")?.id;
const personId = profiles.data.find(p => p.type === "person")?.id;

4. Publish a text post

LinkedIn text posts support up to 3,000 characters. Line breaks render correctly — use them to structure your update. Aether handles the UGC post API call and returns the live post URL.

// Post a text update to a LinkedIn Company Page
const post = await aether.posts.create({
  profileIds: [pageId],
  text: "We just shipped v2.0 of our API platform. Here's what's new 👇\n\n" +
        "• Unified inbox across 7 platforms\n" +
        "• Real-time webhooks with retry logic\n" +
        "• MCP server for AI agent integration\n\n" +
        "Full changelog: https://aetherhq.dev/changelog",
});

console.log(post.status); // "published"
console.log(post.platformResults?.linkedin?.url); // LinkedIn post URL

Posting images and cross-posting

LinkedIn image posts require a two-step upload: register the asset, then attach it to the post. Aether handles both steps when you pass a mediaUrls array. You can also post to a Company Page and personal profile simultaneously with a single API call.

// Post with an image — provide a publicly accessible URL
const imagePost = await aether.posts.create({
  profileIds: [pageId],
  text: "Behind the scenes of our engineering team 📸",
  overrides: {
    linkedin: {
      mediaUrls: ["https://yourcdn.com/team-photo.jpg"],
      altText: "The Aether engineering team at our offsite in Lisbon",
    },
  },
});

// Post to both personal profile and company page in one call
const crossPost = await aether.posts.create({
  profileIds: [pageId, personId],
  text: "Excited to announce our Series A 🎉",
  overrides: {
    linkedin: {
      // LinkedIn strips links from body text — add a commentary field instead
      commentary: "We raised $8M to build the social media API infrastructure layer.",
    },
  },
});

LinkedIn-specific rules to know

  • LinkedIn enforces a 150 API calls/day limit per token — avoid high-frequency polling
  • URLs in post body text are automatically converted to preview cards by LinkedIn, but the URL itself is not clickable in the native app — add your link in the commentary field for best UX
  • Hashtags work in body text: #buildinpublic — up to 3 is best practice
  • Company Page posts require the connected user to be a Super Admin or Content Admin of the page

Next steps

  • Use scheduled posts to queue your LinkedIn content calendar
  • Subscribe to the post.published webhook to sync post URLs back to your CRM
  • Pull post-level analytics — impressions, clicks, reactions — with the analytics API

Ready to build?

One API for Instagram, TikTok, LinkedIn, Facebook, YouTube, Threads, and Reddit. Free tier, no credit card required.

Get started free →