LinkedIn API
Connect LinkedIn personal profiles via OAuth and publish text posts, images, and PDF documents. Scheduling, first-comment, and automatic token refresh included.
One call for text posts, images, and scheduled content. Aether handles token management, content type validation, and retry logic.
import Aether from "aether";
const aether = new Aether({ apiKey: process.env.AETHER_API_KEY });
// Text post to a personal LinkedIn profile
const post = await aether.posts.create({
text: "We just crossed 1,000 developers on Aether 🚀\n\nHere's what we learned building the API layer for social media...",
profileIds: ["prof_li123"],
scheduledFor: "2026-06-15T08:00:00Z",
});
// Image post
const imagePost = await aether.posts.create({
text: "Behind the scenes of our engineering team 📸",
profileIds: ["prof_li123"],
mediaUrls: ["https://your-cdn.com/team-photo.jpg"],
});
// PDF document post
const docPost = await aether.posts.create({
text: "Our Q1 report is live",
profileIds: ["prof_li123"],
mediaUrls: ["https://your-cdn.com/report.pdf"],
overrides: { linkedin: { documentTitle: "Q1 Report" } },
});Free tier · 3 accounts · no credit card
Get your free API keyimport os
import aether
client = aether.Aether(api_key=os.environ["AETHER_API_KEY"])
# Text post to a personal LinkedIn profile
post = client.posts.create(
text="We just crossed 1,000 developers on Aether 🚀\n\nHere's what we learned...",
profile_ids=["prof_li123"],
scheduled_for="2026-06-15T08:00:00Z",
)
# PDF document post
doc_post = client.posts.create(
text="Our Q1 report is live",
profile_ids=["prof_li123"],
media_urls=["https://your-cdn.com/report.pdf"],
overrides={"linkedin": {"documentTitle": "Q1 Report"}},
)curl -X POST https://api.aetherhq.dev/v1/posts \
-H "Authorization: Bearer $AETHER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "We just crossed 1,000 developers on Aether 🚀",
"profileIds": ["prof_li123"],
"scheduledFor": "2026-06-15T08:00:00Z"
}'Aether returns a normalized post object immediately. Once published, publishResults includes the LinkedIn UGC post ID and publish timestamp.
{
"success": true,
"data": {
"id": "post_4n6oq1z",
"status": "scheduled",
"text": "We just crossed 1,000 developers on Aether 🚀",
"profileIds": ["prof_li123"],
"mediaUrls": [],
"mediaKeys": [],
"scheduledFor": "2026-06-15T08:00:00.000Z",
"publishResults": [],
"publishedAt": null,
"failedAt": null,
"createdAt": "2026-06-08T14:23:11.000Z"
}
}Building LinkedIn OAuth yourself means registering a developer app, enabling Share on LinkedIn and OIDC products, handling the authorization code flow, and refreshing tokens every 60 days.
Aether's Connect Link handles that for you. Call one endpoint, get a URL, send it to your user. They click, LinkedIn authenticates them, and their profile appears in your dashboard automatically.
// Generate a Connect Link for your user to authenticate LinkedIn
const link = await aether.connectLinks.create({
platform: "linkedin",
redirectUrl: "https://yourapp.com/settings/social",
});
// Send link.url to your user — they click, authorize on LinkedIn,
// and their personal profile appears in your dashboard automatically.
console.log(link.url); // "https://connect.aetherhq.dev/link/cl_li9q4r..."
console.log(link.expiresAt); // "2026-06-15T14:23:11.000Z"Generate a Connect Link URL — your user authorizes on LinkedIn and their profile appears in your dashboard. No custom OAuth flow to build.
Post on behalf of authenticated personal LinkedIn profiles. Each connected account is a separate profile with its own profileId.
Text posts, image posts, and PDF document posts with optional documentTitle override. Company pages and native video coming soon.
Attach a first comment that publishes immediately after the post goes live — useful for links, CTAs, or follow-up context.
Pass scheduledFor and Aether queues the post for the right time. Works for text, image, and PDF document posts.
LinkedIn access tokens expire after 60 days. Aether tracks expiry per account and refreshes before they lapse.
LinkedIn connect and publish are MCP tools. Claude, Cursor, and any MCP-compatible agent can draft and schedule posts natively.
The LinkedIn Marketing API is powerful but gated. Here is what you take on when building directly versus using Aether.
| Feature | Aether | LinkedIn API directly |
|---|---|---|
| OAuth setup | ✓Connect Links — one endpoint | ✗Build OAuth 2.0 + token refresh yourself |
| Token refresh | ✓Automatic before 60-day expiry | ✗Manual refresh every 60 days |
| Authentication | ✓One API key | ✗Per-app client ID + secret management |
| Content types | ✓Text posts, images, PDF documents | ✗Varies by LinkedIn product approval |
| API maintenance | ✓We absorb breaking changes | ✗Your team's responsibility |
| Platform compliance | Official API, fully compliant | Official API, fully compliant |
Platform-level limits set by LinkedIn. Aether queues and retries automatically — your integration does not need backoff logic.
| Operation | Limit | HTTP status | Note |
|---|---|---|---|
| Member share | ~100 requests / day | 429 | Per member access token |
| Token expiry | 60 days | 401 | Aether auto-refreshes |
| Text post length | 3,000 characters | 422 | UTF-8 |
| Status | Meaning | How Aether handles it |
|---|---|---|
| 401 | Invalid or expired access token | Aether auto-refreshes — reconnect via Connect Link if it persists |
| 403 | Operation not permitted for this member/org | Re-connect via Connect Link to re-request permissions |
| 422 | Content policy violation | Review post content for LinkedIn community standards violations |
| 429 | Rate limit exceeded | Aether queues and retries after the window resets |
| 400 | Invalid request payload or field | Aether validates the request; check input fields and content type |
| 404 | Organization or member not found | Verify profileId is correct and account is still connected |
AI-Native
Aether ships an MCP server that exposes LinkedIn connect and publish as callable tools. Claude Desktop, Cursor, Windsurf, and any MCP-compatible agent can draft and schedule posts — with no additional integration code.
# Add to ~/.claude/claude_desktop_config.json
{
"mcpServers": {
"aether": {
"command": "npx",
"args": ["-y", "aether-mcp"],
"env": { "AETHER_API_KEY": "sk_live_..." }
}
}
}
# Claude can now post to LinkedIn:
# "Draft and schedule a LinkedIn post about our Q2 results for Monday 9am"
# "Post our latest case study to my connected LinkedIn profile now"For self-hosted Aether, yes — create an app at linkedin.com/developers with Share on LinkedIn and Sign In with LinkedIn (OIDC) products enabled. Hosted Aether handles credentials for you.
Yes. Phase 1 supports personal profile posting. The profile owner authorizes via Connect Link, then you post on their behalf programmatically.
Not yet. Company page posting requires LinkedIn Community Management API approval and is planned for a future release.
LinkedIn access tokens expire after 60 days. Aether tracks expiry for every connected account and automatically initiates refresh before they lapse.
Text posts, image posts, and PDF document posts. Articles and native video are not supported yet.
Yes. Aether's MCP server exposes LinkedIn connect and publish as callable tools for Claude, Cursor, and other MCP-compatible agents.
Free tier · 3 accounts · full API access · MCP server · no credit card.
Get your free API key →