Skip to content
SocialsForAI
Menu

Social media API

One API for every feed your agent posts to.

Connect an account once, then publish with a single request. X, Bluesky, LinkedIn, Mastodon and Telegram are live today. Every response says which accounts published, which are retrying, and why.

The short answer · Updated Nov 1, 2026

A social media API lets software publish posts to social networks without a person pressing "post". A unified social media API like SocialsForAI wraps each network's own API (X API v2, LinkedIn's Posts API, Bluesky's AT Protocol) behind one endpoint, one connect flow for account owners and one error format, so an app or AI agent writes one integration instead of one per network.

What we check before a post goes out, per network
NetworkText limitImagesFair-use cap per accountStatus
Bluesky300 graphemes4, up to 2 MB each300 posts / 24hLive
X280 weighted characters (URLs count 23)4, up to 5 MB each100 posts / 24hLive
LinkedIn3,000 charactersUp to 20, up to 20 MB each50 posts / 24hLive, personal profiles only
Mastodon500 characters (URLs count 23), any server4, up to 16 MB each300 posts / 24hLive
Telegram4,096 characters; 1,024 as a caption with imagesUp to 10, up to 10 MB each500 posts / 24hLive, channels and groups via your bot

Limits are the ones our preflight enforces (src/providers). Platform limits come from each network's docs, read 2026-11-01. Video isn't supported on any network yet.

What is a social media API?

A social media API is an HTTP interface that lets code create posts, upload media or read data on a social network. The phrase covers two different products, and search results mix them up.

Posting APIs act for an account that has granted permission: they publish, schedule and delete. Data APIs read public profiles and posts, often by scraping, and sell the results per request. This page is about posting. If you need follower counts or competitor posts, a data API is the tool, and we don't sell one.

Posting APIs come in two shapes. First-party APIs belong to the network: the X API, LinkedIn's Posts API, Bluesky's AT Protocol, Meta's Instagram Graph API, TikTok's Content Posting API. Unified APIs (us, Ayrshare, Postiz's public API and others) sit in front of several first-party APIs and give you one request format for all of them.

What does one API call do?

One POST /v1/posts checks the post against every target network's limits, publishes to each account in parallel, reads the post back where the network allows it, and returns one receipt. You send text, optional media URLs and a list of account ids.

The checks run before anything leaves our servers: length (weighted for X, graphemes for Bluesky), image count, empty posts, the same text on the same account in the last 24 hours, and per-account fair-use caps. They are plain code with no AI calls, so a dry_run: true request costs nothing and posts nothing.

Send an Idempotency-Key header. If your request times out and you retry with the same key and body, you get the original post back with Idempotent-Replayed: true instead of a second post. The same key with a different body returns 409 idempotency_key_reused.

bash
curl https://socialsforai.com/v1/posts \
  -H "Authorization: Bearer $SOCIALS_API_KEY" \
  -H "Idempotency-Key: launch-0412" \
  -d '{
    "accounts": ["acc_bluesky", "acc_linkedin", "acc_x"],
    "text": "We just shipped webhooks.",
    "wait": true
  }'

What does the response look like?

Every post has one target per account, and each target carries its own status, URL, attempt count and error. The post's overall status is published, partially_published, failed, scheduled, publishing or canceled, derived from its targets.

In the response below, Bluesky published and was verified by reading the post back. LinkedIn failed because its 60-day token expired; the error says so and says what to do. With wait: true the call returns after delivery; without it you get 201 straight away and a post.published, post.partially_published or post.failed webhook later.

json
HTTP/1.1 201 Created   (trimmed: media, metadata, target ids and some target fields omitted)

{
  "id": "post_9fQ2mXc4LpZr8TwA",
  "object": "post",
  "status": "partially_published",
  "text": "We just shipped webhooks.",
  "scheduled_at": null,
  "created_at": "2026-11-01T15:04:05.000Z",
  "completed_at": "2026-11-01T15:04:07.000Z",
  "targets": [
    {
      "account_id": "acc_bluesky",
      "platform": "bluesky",
      "status": "published",
      "url": "https://bsky.app/profile/acme.bsky.social/post/3m4xq7k2c2s2a",
      "attempts": 1,
      "verified": true,
      "error": null
    },
    {
      "account_id": "acc_linkedin",
      "platform": "linkedin",
      "status": "failed",
      "url": null,
      "attempts": 1,
      "verified": false,
      "error": {
        "code": "account_needs_reauth",
        "message": "LinkedIn access token expired (they last 60 days).",
        "fix": "Reconnect the LinkedIn account with a new connect link.",
        "retryable": false
      }
    }
  ]
}

What errors come back, and how do you fix them?

Errors that we can predict come back before publishing as a 422 preflight_failed, listing every issue with the account, the field and a fix sentence. Nothing is published when any account fails preflight, so you never get half a launch because one network's text was too long.

Errors from the network itself land on the target. Retryable ones (platform_rate_limited, platform_unavailable, media_fetch_failed on a 5xx) retry after 30 seconds, 2 minutes, 10 minutes, 30 minutes and 2 hours, six attempts in all, then the target becomes failed. Permanent ones stop at once.

  • text_too_long: shorten it, or set platform_options.x.text (or .bluesky, .linkedin) to a per-network version.
  • too_many_media: X and Bluesky take 4 images, LinkedIn 20.
  • duplicate_content: same text, same account, last 24 hours. Vary it or wait.
  • daily_cap_reached: schedule it with scheduled_at instead.
  • account_needs_reauth: send the owner a new connect link; an account.needs_reauth webhook fires when this happens.
  • video_not_supported: video isn't built on any network yet.
  • plan_limit_active_accounts and plan_limit_posts: Free plan limits (3 active accounts, 100 posts a month).
json
HTTP/1.1 422 Unprocessable Entity

{
  "error": {
    "code": "preflight_failed",
    "message": "The post would fail on 1 check(s). Nothing was published.",
    "fix": "Fix the issues below, or send dry_run: true to iterate without publishing.",
    "issues": [
      {
        "account_id": "acc_x",
        "platform": "x",
        "severity": "error",
        "code": "text_too_long",
        "field": "platform_options.x.text",
        "message": "Text is 312 characters; X allows 280.",
        "fix": "Shorten it by 32+ characters, or set platform_options.x.text to a shorter version."
      }
    ]
  }
}

Should you use a network's own API or a unified API?

Use the network's own API when you post to one network, from accounts you control, and need features a unified layer doesn't expose. That is a real and common case, and the first-party route is cheaper and has fewer moving parts.

Use a unified API when you post to two or more networks, or post for other people. Posting for other people is where first-party work grows: each network wants its own developer app, its own review (LinkedIn's Community Management API, Meta's App Review, TikTok's audit) and its own token refresh rules.

  • Go first-party for one Bluesky bot. The AT Protocol has no app review and no fee; our Bluesky API guide shows the raw calls.
  • Go first-party for LinkedIn Company Pages, X polls or quote posts, video, analytics, DMs or reading timelines. We don't do those yet.
  • Go unified when an AI agent posts. Structured code and fix fields, idempotency keys and an MCP server save you writing that layer.
  • Go unified when end users connect their own accounts and you don't want to hold their tokens or build reconnect flows.

How do accounts get connected?

The account owner opens a hosted connect link: OAuth for X and LinkedIn, an app password for Bluesky, the server URL and an access token for Mastodon, and a bot token plus channel or group for Telegram. You never see their password, and stored credentials are encrypted with AES-256-GCM and deleted on disconnect.

Tag the link with external_ref (your client id or user id) and every account it creates carries it. Links expire after 7 days by default, configurable from 5 minutes to 30 days. Set redirect_url and the owner lands back in your app with account_id, platform and status=connected in the query string.

bash
curl https://socialsforai.com/v1/connect-links \
  -H "Authorization: Bearer $SOCIALS_API_KEY" \
  -d '{
    "platforms": ["bluesky", "linkedin"],
    "external_ref": "client_42",
    "redirect_url": "https://yourapp.example/connected"
  }'

# 201 → { "id": "cl_...", "object": "connect_link", "url": "...", "expires_at": "..." }

How much does a social media API cost?

First-party posting is cheap or free in money: Bluesky charges nothing, LinkedIn publishes no per-call price, and X charges $0.015 per post and $0.200 per post with a link. The cost is engineering and review time. See X API pricing and LinkedIn API pricing for the detail.

We charge per active account, meaning one that published that month. Free covers 3 active accounts and 100 posts a month; Hobby is $9 for 5; Pro is $29 for 25; Growth is $79 for 100. Posts are unlimited on paid plans and X's fees pass through at cost. Paid billing isn't switched on yet, so every workspace starts on Free. Full table on pricing.

Other unified APIs price differently: Ayrshare starts at $149 a month for one profile, Postiz at $29 for 5 channels (read on their pricing pages). The comparisons are at vs Ayrshare and vs Postiz.

Can an AI agent use the API directly?

Yes. The same operations are exposed as an MCP server over Streamable HTTP at /api/mcp, with tools for listing platforms and accounts, creating connect links, creating, reading and canceling posts, and checking usage. create_post waits for delivery by default so the agent sees the result in the same turn.

An agent can even get its own key: POST /v1/workspaces returns a Free-plan API key without a browser. Setup for Claude Code is one command.

bash
claude mcp add --transport http socials https://socialsforai.com/api/mcp \
  --header "Authorization: Bearer $SOCIALS_API_KEY"

From zero to a published post

  1. 01

    Get a key

    POST /v1/workspaces returns a Free-plan API key. Store it; it isn't shown again. Agents can do this step themselves.

  2. 02

    Send a connect link

    POST /v1/connect-links returns a URL. The account owner opens it, approves access, and the account appears in GET /v1/accounts.

  3. 03

    Dry-run the post

    POST /v1/posts with dry_run set to true returns every issue with a fix and a per-account preview of the text, and publishes nothing.

  4. 04

    Publish

    Send it for real with wait set to true and an Idempotency-Key header. Retrying with the same key never posts twice.

  5. 05

    Listen for webhooks

    Register an endpoint with POST /v1/webhooks. Payloads are signed with HMAC-SHA256 in the Socials-Signature header, and failed deliveries retry on a schedule from 1 minute to 24 hours.

Questions

What developers ask

What is the best social media API for developers?

It depends on the networks and who owns the accounts. For one network and your own account, that network's API is simplest. For several networks, or for accounts your users own, a unified API saves building OAuth, token refresh and error handling per network. Compare pricing models too: per profile, per channel or per active account.

Which networks can I post to with SocialsForAI?

X, Bluesky, LinkedIn personal profiles, Mastodon and Telegram are live. Instagram, Threads, Facebook, TikTok, YouTube, Pinterest and Reddit are coming and need platform review or are not built yet. Video isn't supported on any network yet. GET /v1/platforms reports live status from the server's configuration.

Is there a free social media API?

Bluesky's API is free to use for posting. LinkedIn doesn't charge per call for member posts. X charges per request with no free posting tier on its pricing page. Our Free plan covers 3 active accounts and 100 posts a month with every feature, so you can build and test without paying.

Do I need my own developer app on each network?

Not with a unified API. Account owners connect through our apps with a connect link, and you hold one API key. If you go first-party instead, you register an app on each network and pass each network's review before posting for anyone outside your own team.

Is there a dashboard?

No, on purpose. Everything runs through the REST API, the MCP server and webhooks. If you want a calendar and a drag-and-drop composer for a social media team, a scheduler like Postiz or Buffer is the better fit, and our comparison pages say so.

What happens if a post fails on one network?

The other accounts still publish. The post comes back partially_published, the failed account carries an error with a code, a message and a fix, and transient errors retry on their own at 30 seconds, 2, 10 and 30 minutes and 2 hours before the target is marked failed.

Get an API key and send your first post in five minutes.