Back to blog
Tool guides12 min readPublished September 12, 2026

Social media posting APIs: what each platform actually lets you publish

A per-platform reference for publishing programmatically: the auth model, the approval hoop, the endpoint that creates a post, and the limit that bites you in production. Covers X, LinkedIn, Facebook, Instagram, Threads, YouTube, Reddit, Bluesky, Mastodon, Discord and Slack, with two runnable requests and an honest build-versus-buy line.

What this solves

A developer is about to build programmatic posting and wants to know, per platform, what the auth model is, whether an approval process stands in the way, and what the API is actually permitted to publish.

How S2P helps

You can decide which platforms to integrate directly, which to skip, and where the real cost sits. You leave with the endpoint shape and the approval hoop for each of the eleven platforms that publish through an API, plus two requests you can run today.

Key takeaways

  • There is no single social media API. Every platform ships its own, and the integration cost lives in the differences between them, not in the HTTP.
  • The hard part is never the publish call. It is OAuth per platform, token refresh, media upload as a separate multi-step request, and app review.
  • Bluesky, Mastodon, Discord webhooks and Slack incoming webhooks need no review at all. LinkedIn, Instagram, Threads, Facebook Pages and TikTok all gate public publishing behind a human.
  • Free means something different per platform: X charges per write request, YouTube meters uploads daily, and Meta costs nothing to call but requires App Review to reach real users.
  • Build direct for one or two platforms. Stop building at the point where token refresh and app review become someone's recurring job.

Section 1

What a social media API is, and the three kinds you will meet

The phrase covers three different access grants that platforms hand out separately, and confusing them is how integrations get rejected.

A social media API is an HTTP interface a platform publishes so software can act on an account without driving a browser. In practice the term collapses three distinct things. A posting API, sometimes listed as a social media post API, writes content: it creates a post, uploads media, replies to a thread. A social media analytics API reads performance data back for content you already own. A social media listening API, sometimes sold as a social media monitoring API, reads other people's public content at volume.

Platforms grant these separately and price them separately. LinkedIn treats publishing and page analytics as different use cases inside the same access request form; Meta reviews publishing permissions and insights permissions independently. Approval for one is not approval for another, and listening access is the hardest of the three to get.

This page covers the first kind only. When someone asks for an API for social media, writing a post is almost always what they mean, and it is the only one of the three a small team can realistically ship in a week.

  • Posting API: creates content on an account you or your user controls.
  • Analytics API: reads metrics for content that account already published.
  • Listening or monitoring API: reads public content across the platform. Separately granted, rarely approved for small teams.
  • A single OAuth token usually carries scopes for only the grant you were approved for.

Section 2

The per-platform reference

Auth model, approval hoop, the call that creates a post, and the constraint that will surprise you in production.

Every row below was read on the platform's own developer documentation. The column that matters most is the third one: the publish call is a few lines in any language, and the approval hoop is what decides whether your integration ships this month or next quarter.

One pattern runs through the whole table. The platforms with the largest audiences gate public publishing behind a human reviewing a recording of your product. The ones with no review at all are the newer or federated networks, plus the two chat surfaces where a webhook URL is the entire authentication story.

Posting APIs by platform, verified August 2026

PlatformAuth modelApproval hoopWhat creates a postPractical constraint
XOAuth 2.0 user context; app-only bearer for app-level callsDeveloper account plus prepaid credits; no subscription tierPOST /2/tweetsWrites are billed per request, and docs.x.com prices a post containing a URL far higher than a plain one
LinkedInOAuth 2.0 with w_member_social or w_organization_socialCommunity Management API, Development tier then Standard tier with a screencast reviewPOST https://api.linkedin.com/rest/postsCommunity Management must be the only product on the app, and organization posting needs a Page admin role
Facebook PagePage access token via Facebook Login, pages_manage_postsApp Review for Advanced Access, plus business verificationPOST /{page-id}/feedStandard Access only works for people who hold a role on your app
InstagramInstagram Login or Facebook Login, instagram_content_publishApp Review; professional account only; Page Publishing AuthorizationCreate a media container, then publish it100 API-published posts per rolling 24 hours; a carousel counts as one
ThreadsOAuth with threads_basic and threads_content_publishApp Review and a published app before non-testers can grant permissionPOST /{threads-user-id}/threads then /threads_publish250 published posts per 24 hours; permission grants expire after 90 days
YouTubeGoogle OAuth 2.0Google Cloud project with the Data API v3 enabledvideos.insertDefault allocation is 100 videos.insert calls per day, separate from the 10,000-unit daily budget
RedditOAuth 2.0 with a registered client and a unique descriptive User-AgentRegister an app for a client ID; read the developer terms before commercial useThe submit endpoint on the Data APIBudget is per OAuth client and reported in X-Ratelimit headers; subreddit rules decide whether the post survives
Blueskycom.atproto.server.createSession with an app password, or OAuthNone. Self-serve.An app.bsky.feed.post record written over the /xrpc/ surfaceWith app passwords you hold a long-lived credential; OAuth is the protocol's primary scheme
MastodonPer-server OAuth app via POST /api/v1/apps, scope write:statusesNone, but registration happens on every instance separatelyPOST /api/v1/statusesClient credentials do not transfer between servers, so N instances means N registrations
DiscordWebhook token in the URL, no auth header; or a bot tokenNone for webhooksPOST /webhooks/{webhook.id}/{webhook.token}A webhook is bound to one channel and posts as itself, not as a user; content is capped at 2000 characters
SlackIncoming webhook URL from an app holding the incoming-webhook scopeWorkspace install; Marketplace review only if you distribute publiclyPOST the JSON payload to the webhook URLThe channel is fixed at install time and a webhook cannot delete a message it sent

Section 3

One real request, end to end

LinkedIn is the highest-value target for most developer tools and the clearest example of what a publish call actually looks like.

If you want to automate LinkedIn posts, this is the request. LinkedIn's Posts API replaces the older ugcPosts API, and a text post is a single POST to https://api.linkedin.com/rest/posts. The two headers people forget are Linkedin-Version, a version string in YYYYMM format, and X-Restli-Protocol-Version, which must be 2.0.0. A successful create returns 201 with the post URN in the x-restli-id response header.

Change the author URN to urn:li:person:{id} and the required scope becomes w_member_social instead of w_organization_social. That one field is the whole difference between posting as a company page and posting as a person.

Note what the request does not do. LinkedIn's documentation states the Posts API does not scrape URLs for article posts, so if you want a link preview you set the thumbnail, title and description yourself after uploading the image through the Images API. Every platform has one of these: a thing you assumed was automatic that turns out to be your job.

Publish a text post as an organization

curl -X POST 'https://api.linkedin.com/rest/posts' \
  -H 'Authorization: Bearer {INSERT_TOKEN}' \
  -H 'X-Restli-Protocol-Version: 2.0.0' \
  -H 'Linkedin-Version: 202608' \
  -H 'Content-Type: application/json' \
  --data '{
    "author": "urn:li:organization:5515715",
    "commentary": "v1.4.0 is out. Streaming diffs, and a rewritten config loader.",
    "visibility": "PUBLIC",
    "distribution": {
      "feedDistribution": "MAIN_FEED",
      "targetEntities": [],
      "thirdPartyDistributionChannels": []
    },
    "lifecycleState": "PUBLISHED",
    "isReshareDisabledByAuthor": false
  }'

Section 4

What free actually means, platform by platform

Free to call and free to use are different questions, and the honest answer usually involves a review process rather than a price.

X is the clearest case of a platform that changed. It no longer sells fixed Basic and Pro subscription tiers; the X API now runs on pay-per-usage, where you buy credits up front in the Developer Console and they are deducted per request. Writes are billed individually, and the pricing page lists a materially higher per-request price for a post containing a URL than for one without. Release announcements contain a link by definition, so price the expensive row.

Meta is the opposite shape. Calling the Graph API, the Instagram content-publishing endpoints or the Threads API costs nothing. The cost is App Review. Under Standard Access a permission can only be requested from people who already hold a role on your app, which is fine for an internal tool and useless for a product. Advanced Access, the level any real user needs, requires business verification and a review in which Meta tests your app.

YouTube is free but metered: Google's quota documentation gives a project 100 videos.insert calls per day, 100 search.list calls per day, and 10,000 units per day shared across everything else. Reddit is free to call with a registered OAuth client and a descriptive User-Agent, but read Reddit's developer terms before you ship anything commercial on it.

  • X: prepaid credits, charged per request, higher price for posts containing a URL.
  • Facebook, Instagram, Threads: no call cost, App Review required before anyone outside your app roster can use it.
  • YouTube: free, capped at 100 videos.insert calls per day by default.
  • Reddit: free with a registered OAuth client; commercial use is governed by separate developer terms.
  • Bluesky, Mastodon, Discord, Slack: free, no review, self-serve.
  • TikTok: the Content Posting API exists and needs the video.publish scope, but content from an unaudited client is restricted to private viewing.

Section 5

Why a multi-platform integration is harder than eleven POST requests

The publish call is the small part. Four other things consume the engineering time, and they recur forever.

Every platform runs its own OAuth flow with its own scope names, its own consent screen and its own token lifetime. You will store a different credential shape per platform, refresh some of them on a schedule, and handle the case where a user revokes access silently. Threads adds a wrinkle most do not: permission grants expire after 90 days for accounts with public profiles, so a working integration stops working without anyone touching it.

Media is rarely one call. Instagram and Threads both use a two-step container model: you POST the media to create a container, wait for the platform to finish processing it, then POST again to publish that container. Meta's Threads documentation recommends waiting roughly 30 seconds between the two. LinkedIn splits it further, with separate Images, Videos and Documents APIs that each return a URN you then reference from the post body. None of this is difficult; all of it is state you now own.

Rate limits are not even shaped the same way. X documents POST /2/tweets at 10,000 per 24 hours per app and 100 per 15 minutes per user, so you can exhaust the user window while the app window is barely touched. Instagram and Threads count published posts against a rolling 24-hour window. YouTube counts uploads against a daily call allocation instead. A single retry policy will not fit all four.

Then there is app review, which is the only item on this list that a better architecture cannot help with. LinkedIn requires a Development tier approval, then a Standard tier request with a downloadable screen recording demonstrating a user completing OAuth and posting through your product. Meta tests your app itself and rejects the submission if reviewers cannot reach it. Both are measured in weeks, and both must be redone when your functionality changes materially.

Section 6

How to post to multiple platforms at once for free

If you want fan-out today without a review queue, four destinations will take your post with no approval process at all.

To post to multiple social media accounts at once for free, start with the platforms that have no gatekeeper: Discord, Slack, Bluesky and Mastodon. Discord's Execute Webhook endpoint explicitly does not require authentication, because the token is part of the URL, and Slack's incoming webhooks work the same way once an app carrying the incoming-webhook scope is installed. Both take a JSON body over a plain POST, and the only real difference is the field name: Discord reads content, Slack reads text.

Bluesky and Mastodon extend the same idea to public social, and neither has a review process. Bluesky's AT Protocol exposes procedures under a /xrpc/ path; a client calls com.atproto.server.createSession with an account identifier and a password, where an app password is the supported credential for third-party clients. Mastodon requires registering an application on each server with POST /api/v1/apps, then posting with the write:statuses scope. Five servers means five registrations.

What this free path does not get you is the audience most products care about. LinkedIn, Instagram and Facebook are not on it, and no amount of engineering skips their review. Treat the zero-review set as the first release of your integration, not the whole of it.

Fan out to Discord and Slack with no OAuth flow

# Discord: the webhook token in the URL is the entire auth story
curl -sS -X POST "$DISCORD_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{"content":"v1.4.0 is out. Streaming diffs, and a rewritten config loader."}'

# Slack: same request shape, different field name
curl -sS -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{"text":"v1.4.0 is out. Streaming diffs, and a rewritten config loader."}'

Section 7

Build direct, or buy a layer

Both answers are correct in different places, and the dividing line is maintenance rather than difficulty.

Build direct when you need one or two platforms and the account you post to is your own. A Bluesky adapter is an afternoon; a Discord webhook is ten minutes. You keep platform-specific features, you pay nothing extra, and there is no vendor between you and the API when something breaks. If your entire requirement is announcing releases into your own Discord server, stop reading and go write it.

Buy a layer when the count goes up and the accounts belong to other people. This is where social media automation stops being a feature you wrote and starts being infrastructure you maintain. At three or four platforms the recurring work is no longer the adapters; it is token refresh, expiring grants, App Review resubmissions when Meta changes a requirement, and per-platform rate-limit handling. That is a standing claim on someone's week, forever. The cost of buying is a dependency you did not write and a ceiling on platform-specific features you did not anticipate needing.

The middle answer, which is often the right one: build direct for the one or two platforms that matter most to your product and where you want native control, and take a layer for the long tail you would otherwise never get round to.

Section 8

Where Ship 2 Post fits, and where it does not

Ship 2 Post is a GitHub-triggered release-marketing pipeline with an API on top, not a general-purpose posting API.

The trigger is a GitHub event. A release, a tag, a merged pull request or a deployment arrives through the Ship 2 Post GitHub App, a rule decides on semver, branch, path, label and repo scope whether it qualifies, and the pipeline drafts channel-native variants. Those go to a review queue for one-click approval, or publish without a stop if you switch that channel to autonomous mode. If what you need is to publish arbitrary copy from your own scheduler, this is the wrong tool and the platform APIs above are the right ones.

What Ship 2 Post does expose is a bearer-authenticated /v1 surface with a published OpenAPI 3.1 document at GET /v1/openapi.json. API access requires the Growth plan or higher; a key on the Free or Starter plan gets 403 plan_required on every call. Keys are workspace-scoped and scope-checked on each request.

The limits, stated plainly, because they are the ones that would waste your afternoon. There is no POST /v1/drafts, so a draft cannot be created without a release signal behind it. There is no scheduling feature of any kind. There is no public retry endpoint: re-publishing a variant whose previous attempt failed returns 409 conflict, and retry lives in the in-app queue instead. Outbound webhooks are not HMAC-signed, so a receiver has no signature header to verify and must treat the webhook URL as the secret and de-duplicate on the idempotency key in the payload.

There are 14 destinations. Eleven are native platform integrations: LinkedIn, X, Threads, Bluesky, Reddit, Facebook, Instagram, YouTube, Mastodon, Discord and Slack. The other three, Hacker News, Substack and custom webhook, share one outbound-webhook adapter that POSTs to a URL you supply. Of the eleven, only Bluesky and Mastodon connect headlessly; the rest need a browser OAuth round trip once, for exactly the reasons the table above describes.

curl

export S2P_BASE="https://<deployment>.convex.site"
export S2P_KEY="s2p_<your-bearer-token>"

# poll for the drafts a release signal produced
curl -sS "$S2P_BASE/v1/drafts?signal_id=$SIGNAL_ID&status=ready" \
  -H "Authorization: Bearer $S2P_KEY"

# approve one, which enqueues the publish fan-out
curl -sS -X POST "$S2P_BASE/v1/drafts/approve?id=$DRAFT_ID" \
  -H "Authorization: Bearer $S2P_KEY"

FAQ

Questions this article answers

What is a social media API?

A social media API is an HTTP interface a platform publishes so software can act on an account without a browser. The term covers three separate grants: posting APIs that create content, analytics APIs that read metrics for content you own, and listening or monitoring APIs that read public content at volume. Platforms approve and price these independently, so access to one does not imply access to another.

Is there a free social media API available?

Several. Bluesky, Mastodon, Discord webhooks and Slack incoming webhooks are free and need no review process. YouTube's Data API is free but capped by a daily quota allocation. Meta's Facebook, Instagram and Threads APIs cost nothing to call but require App Review before anyone outside your app's roster can grant permission. X is the exception: it now runs on prepaid credits charged per request.

Is Instagram's API free?

Calling it is free. Using it is gated. Instagram content publishing requires a professional account, the instagram_content_publish permission, and App Review before people who lack a role on your app can authorize it. Accounts on Pages that need Page Publishing Authorization cannot publish until that is completed. The API also caps you at 100 API-published posts in any rolling 24-hour period, with a carousel counting as one.

Is TikTok an API?

TikTok publishes a Content Posting API that can post videos and photos directly to an authorized creator account. It requires the video.publish scope, approved for both your app and the target user. The catch is the audit: TikTok's documentation states that content posted by unaudited clients is restricted to private viewing mode, so public publishing requires passing a compliance audit first.

What is an app that allows me to post to all social media platforms at once?

Unified posting layers exist that sit on top of the native APIs and expose one endpoint for many platforms. None of them covers every platform, because each one still depends on that platform granting it access. Before choosing one, check which destinations it actually supports natively, which it relays through a webhook, and whether it has cleared App Review for the platforms you care about most.

Is there a free way to automate social media posting?

Yes, on the platforms with no approval process. A Discord Execute Webhook needs no authentication at all because the token is in the URL. A Slack incoming webhook needs one app install. Bluesky authenticates with an app password over the AT Protocol, and Mastodon with a per-server OAuth app. All four accept a plain JSON POST and cost nothing. LinkedIn, Instagram and Facebook cannot be reached this way.

Related guides and pages

Where to go next

Hand-picked pages that go deeper on the workflow, channels, and tooling covered above.

Ship 2 Post

Stop writing release posts.

Your engineers already commit. Now those commits become content - in your voice, on every channel.