# How to Automate Social Media Posting with an API (Step-by-Step) > Stop manually posting to 11 platforms. This guide shows you how to automate social media publishing using a REST API — with code examples in Python, Node.js, and cURL. **Source:** https://posteverywhere.ai/blog/automate-social-media-posting-api **Author:** Jamie Partridge **Published:** 2026-03-23 --- Clicking "publish" across Instagram, TikTok, LinkedIn, Facebook, X, YouTube, and Threads every time you have a new post is not a workflow. It is a waste of engineering hours. If you are building a content pipeline, an AI agent, a CMS integration, or anything that produces social content at scale — you need an API. This guide walks you through automating social media posting with a REST API, step by step. Every code example uses [PostEverywhere's API](/social-media-api) because it is the fastest way to go from zero to publishing across all 11 platforms with a single HTTP request. If you prefer a typed client, install the [official `@posteverywhere/sdk` SDK on npm](https://www.npmjs.com/package/@posteverywhere/sdk) with `npm install @posteverywhere/sdk`. Source available on [GitHub](https://github.com/posteverywhere/sdk). If you would rather not write code, we cover [the routes that need no integration at all](/blog/auto-post-to-all-social-media). ## Table of Contents 1. [Why Automate with an API Instead of a Dashboard](#why-automate-with-an-api-instead-of-a-dashboard) 2. [What You Need Before Starting](#what-you-need-before-starting) 3. [Step 1: Get Your API Key](#step-1-get-your-api-key) 4. [Step 2: List Your Connected Accounts](#step-2-list-your-connected-accounts) 5. [Step 3: Create and Schedule a Post](#step-3-create-and-schedule-a-post) 6. [Step 4: Upload Media](#step-4-upload-media) 7. [Step 5: Schedule with AI-Generated Content](#step-5-schedule-with-ai-generated-content) 8. [Step 6: Check Post Status](#step-6-check-post-status) 9. [Common Automation Patterns](#common-automation-patterns) 10. [Error Handling and Rate Limits](#error-handling-and-rate-limits) 11. [FAQs](#faqs) ## Why Automate with an API Instead of a Dashboard A dashboard is fine when one person manages one brand. But the moment any of these apply, you need an API: - **CI/CD pipelines** — push a blog post to your CMS and automatically distribute it across social platforms - **[AI content agents](/agents)** — let your LLM generate content and publish it without human intervention, the approach we cover in [automating social media with AI agents](/blog/how-to-automate-social-media-with-ai-agents) - **Bulk operations** — schedule 500 posts from a CSV in seconds instead of clicking through a calendar - **Multi-tenant apps** — agencies and [SaaS products](https://saaspirate.com/) that manage posting for dozens of clients - **Event-driven publishing** — trigger posts when a product launches, a price drops, or a webhook fires Each network meters requests differently ([the full comparison](/blog/social-media-api-rate-limits)). The [PostEverywhere API](https://app.posteverywhere.ai/api/v1) gives you a single REST endpoint for all 11 platforms, with no per-post fee (worth noting, since [X now bills per call](/blog/x-twitter-api-pricing)). One auth token, one request format, one response structure. No juggling the Meta Graph API, Twitter API v2, LinkedIn Marketing API, and TikTok Content Posting API separately. ## What You Need Before Starting Before writing any code, you need three things: 1. **A PostEverywhere account** — any plan works, including the [7-day free trial](/pricing). API access is included on every plan, from Lite ($9/mo) up. 2. **Connected social accounts** — link your Instagram, TikTok, LinkedIn, Facebook, X, YouTube, and/or Threads accounts from the dashboard. 3. **An API key** — generated from your [developer settings](/docs/authentication). That is it. No OAuth app registration, no developer portal applications, no approval processes. You get your key and start making requests immediately. ## Step 1: Get Your API Key Head to your [PostEverywhere developer settings](/docs/authentication) and generate an API key. Your key looks like this: ``` pe_live_a1b2c3d4e5f6g7h8i9j0... ``` All requests use Bearer token authentication. Add this header to every request: ``` Authorization: Bearer pe_live_a1b2c3d4e5f6g7h8i9j0... ``` Store your API key securely. Use environment variables — never hardcode it. > **Ready to automate your social media?** [Start your free 7-day trial](/pricing) — API access included on every plan. cancel anytime. ## Step 2: List Your Connected Accounts Before scheduling posts, you need the account IDs for each connected platform. Here is how to fetch them. **cURL:** ```bash curl -X GET https://app.posteverywhere.ai/api/v1/accounts \ -H "Authorization: Bearer $PE_API_KEY" \ -H "Content-Type: application/json" ``` **Python:** ```python import requests import os api_key = os.environ["PE_API_KEY"] headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } response = requests.get( "https://app.posteverywhere.ai/api/v1/accounts", headers=headers ) accounts = response.json()["data"] for account in accounts: print(f"{account['platform']}: {account['id']} ({account['name']})") ``` **Node.js:** ```javascript const response = await fetch("https://app.posteverywhere.ai/api/v1/accounts", { method: "GET", headers: { "Authorization": `Bearer ${process.env.PE_API_KEY}`, "Content-Type": "application/json" } }); const { data: accounts } = await response.json(); accounts.forEach(account => { console.log(`${account.platform}: ${account.id} (${account.name})`); }); ``` **Example response:** ```json { "data": [ { "id": "acc_123", "platform": "instagram", "name": "@yourbrand" }, { "id": "acc_456", "platform": "linkedin", "name": "Your Company" }, { "id": "acc_789", "platform": "tiktok", "name": "@yourbrand" }, { "id": "acc_012", "platform": "facebook", "name": "Your Page" }, { "id": "acc_345", "platform": "x", "name": "@yourbrand" }, { "id": "acc_678", "platform": "youtube", "name": "Your Channel" }, { "id": "acc_901", "platform": "threads", "name": "@yourbrand" } ] } ``` Save those account IDs. You will reference them in every post request. See the full [Accounts endpoint documentation](/docs/api/list-accounts) for filtering and pagination options. ## Step 3: Create and Schedule a Post This is the core of the API. One request creates a post and schedules it to one or more platforms at a specific time. No need to make 7 separate API calls. **cURL:** ```bash curl -X POST https://app.posteverywhere.ai/api/v1/posts \ -H "Authorization: Bearer $PE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "Just shipped our new API docs. Automate your social media posting with a single endpoint.\n\nCheck it out: https://posteverywhere.ai/developers", "platforms": ["instagram", "linkedin", "x", "facebook", "threads"], "account_ids": ["acc_123", "acc_456", "acc_345", "acc_012", "acc_901"], "scheduled_at": "2026-03-24T09:00:00Z" }' ``` **Python:** ```python import requests import os payload = { "content": ( "Just shipped our new API docs. Automate your social media " "posting with a single endpoint.\n\n" "Check it out: https://posteverywhere.ai/developers" ), "platforms": ["instagram", "linkedin", "x", "facebook", "threads"], "account_ids": ["acc_123", "acc_456", "acc_345", "acc_012", "acc_901"], "scheduled_at": "2026-03-24T09:00:00Z" } response = requests.post( "https://app.posteverywhere.ai/api/v1/posts", headers={ "Authorization": f"Bearer {os.environ['PE_API_KEY']}", "Content-Type": "application/json" }, json=payload ) post = response.json()["data"] print(f"Post {post['id']} scheduled for {post['scheduled_at']}") ``` **Node.js:** ```javascript const response = await fetch("https://app.posteverywhere.ai/api/v1/posts", { method: "POST", headers: { "Authorization": `Bearer ${process.env.PE_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ content: "Just shipped our new API docs. Automate your social media posting with a single endpoint.\n\nCheck it out: https://posteverywhere.ai/developers", platforms: ["instagram", "linkedin", "x", "facebook", "threads"], account_ids: ["acc_123", "acc_456", "acc_345", "acc_012", "acc_901"], scheduled_at: "2026-03-24T09:00:00Z" }) }); const { data: post } = await response.json(); console.log(`Post ${post.id} scheduled for ${post.scheduled_at}`); ``` That is a single request to schedule across 5 platforms. The API handles platform-specific formatting, character limits, and publishing. Check the full [Posts endpoint documentation](/docs/api/reference) for all available fields including hashtags, first comments, and link previews. ## Step 4: Upload Media Most social posts need images or video. PostEverywhere uses a presigned URL flow — you request an upload URL, push your file directly to storage, then attach the media ID to your post. The [social media API](/social-media-api) handles upload, formatting, and delivery across every platform. **Step 4a: Get a presigned upload URL** ```bash curl -X POST https://app.posteverywhere.ai/api/v1/media/upload \ -H "Authorization: Bearer $PE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "filename": "product-launch.jpg", "content_type": "image/jpeg" }' ``` **Response:** ```json { "data": { "media_id": "med_abc123", "upload_url": "https://media.posteverywhere.ai/uploads/...", "expires_at": "2026-03-23T12:30:00Z" } } ``` **Step 4b: Upload the file to the presigned URL** ```bash curl -X PUT "https://media.posteverywhere.ai/uploads/..." \ -H "Content-Type: image/jpeg" \ --data-binary @product-launch.jpg ``` **Step 4c: Attach the media to a post** ```python payload = { "content": "Our new product just dropped. Link in bio.", "platforms": ["instagram", "tiktok", "facebook", "linkedin", "x", "youtube", "threads"], "account_ids": ["acc_123", "acc_789", "acc_012", "acc_456", "acc_345", "acc_678", "acc_901"], "media_ids": ["med_abc123"], "scheduled_at": "2026-03-25T14:00:00Z" } response = requests.post( "https://app.posteverywhere.ai/api/v1/posts", headers=headers, json=payload ) ``` You can attach multiple media IDs for carousel posts on Instagram and LinkedIn. See the full [Media endpoint documentation](/docs/quick-start) for supported file types, size limits, and video processing details. ## Step 5: Schedule with AI-Generated Content If you want the API to generate your captions, images, or both — use the [AI endpoint](/docs/quick-start). This is especially useful for bulk automation where writing unique captions for every post is not practical. **Python example — generate a caption and schedule it:** ```python # Step 1: Generate AI content ai_response = requests.post( "https://app.posteverywhere.ai/api/v1/ai/generate", headers=headers, json={ "prompt": "Write an engaging social media post about our new API documentation launch", "tone": "professional", "platforms": ["linkedin", "x", "instagram"] } ) generated = ai_response.json()["data"] # Step 2: Schedule the generated content for platform, content in generated["content"].items(): requests.post( "https://app.posteverywhere.ai/api/v1/posts", headers=headers, json={ "content": content["text"], "platforms": [platform], "account_ids": [account_map[platform]], "scheduled_at": "2026-03-26T10:00:00Z" } ) ``` The AI endpoint generates platform-optimized content. A LinkedIn post gets a professional tone with line breaks. An X post stays under 280 characters. An Instagram caption includes relevant hashtags. This is the same [AI content generator](/ai-content-generator) that powers the dashboard — available programmatically. > **Building an AI content pipeline?** PostEverywhere's API handles generation, scheduling, and publishing in one workflow. [See the developer docs](/developers) to get started. ## Step 6: Check Post Status After scheduling, you can poll for status updates to confirm your posts published successfully. **cURL:** ```bash curl -X GET https://app.posteverywhere.ai/api/v1/posts/post_xyz789 \ -H "Authorization: Bearer $PE_API_KEY" ``` **Response:** ```json { "data": { "id": "post_xyz789", "status": "published", "platforms": [ { "platform": "instagram", "status": "published", "published_at": "2026-03-24T09:00:03Z", "url": "https://instagram.com/p/..." }, { "platform": "linkedin", "status": "published", "published_at": "2026-03-24T09:00:01Z", "url": "https://linkedin.com/feed/update/..." }, { "platform": "x", "status": "published", "published_at": "2026-03-24T09:00:02Z", "url": "https://x.com/.../status/..." } ] } } ``` Possible status values: `draft`, `scheduled`, `publishing`, `published`, `failed`. If a post fails on one platform but succeeds on others, you get per-platform status so you can retry only the failures. ## Common Automation Patterns Once you have the basics working, these are the patterns that save the most time. ### Daily Scheduler (Cron Job) Run a script every morning that pulls content from your CMS and schedules it across platforms: ```python # cron: 0 6 * * * python schedule_daily.py import requests, os from datetime import datetime, timedelta headers = {"Authorization": f"Bearer {os.environ['PE_API_KEY']}"} # Fetch today's content from your CMS posts = fetch_from_cms(date=datetime.today()) for i, post in enumerate(posts): scheduled_time = datetime.now().replace(hour=9) + timedelta(hours=i * 3) requests.post( "https://app.posteverywhere.ai/api/v1/posts", headers=headers, json={ "content": post["caption"], "platforms": post["platforms"], "account_ids": post["account_ids"], "media_ids": post.get("media_ids", []), "scheduled_at": scheduled_time.isoformat() + "Z" } ) ``` ### RSS-to-Social Pipeline Automatically share new blog posts as social content using a webhook or polling approach. Pair this with PostEverywhere's [AI content generator](/ai-content-generator) to create unique captions for each platform instead of just sharing the title and link. ### AI Content Pipeline Build an end-to-end pipeline: generate content with your LLM, generate images with the [AI image endpoint](/docs/quick-start), format for each platform, schedule at [optimal times](/best-time-to-post), and monitor results — all without touching the dashboard. If your pipeline runs inside Claude Code or another AI agent, our [Claude Code MCP integration](https://www.npmjs.com/package/@posteverywhere/mcp) (run `npx -y @posteverywhere/mcp`, source on [GitHub](https://github.com/posteverywhere/mcp)) exposes the same endpoints as native tools so the agent can schedule posts directly. ### Bulk CSV Upload Have a spreadsheet of 200 posts? Parse the CSV and loop through the [Posts endpoint](/docs/api/reference): ```python import csv with open("posts.csv") as f: reader = csv.DictReader(f) for row in reader: requests.post( "https://app.posteverywhere.ai/api/v1/posts", headers=headers, json={ "content": row["caption"], "platforms": row["platforms"].split(","), "account_ids": row["account_ids"].split(","), "scheduled_at": row["scheduled_at"] } ) ``` This replaces hours of manual scheduling with seconds of execution. PostEverywhere's [social media scheduler](/social-media-scheduler) handles the rest — formatting, publishing, and error recovery. ## Error Handling and Rate Limits The API enforces rate limits to keep things stable for everyone. See the full [rate limits documentation](/docs/rate-limits) for details. | Limit | Threshold | |-------|-----------| | Per minute | 60 requests | | Per hour | 1,000 requests | When you hit a rate limit, you get a `429 Too Many Requests` response with a `Retry-After` header. Handle it gracefully: ```python import time def api_request(method, url, **kwargs): response = requests.request(method, url, headers=headers, **kwargs) if response.status_code == 429: retry_after = int(response.headers.get("Retry-After", 60)) time.sleep(retry_after) return api_request(method, url, **kwargs) response.raise_for_status() return response.json() ``` **Common error codes:** | Code | Meaning | Fix | |------|---------|-----| | 400 | Bad request | Check your payload format | | 401 | Unauthorized | Verify your API key | | 403 | Forbidden | Account not connected or insufficient permissions | | 404 | Not found | Post or account ID does not exist | | 429 | Rate limited | Back off and retry after the specified interval | | 500 | Server error | Retry with exponential backoff | For production systems, implement exponential backoff, log failures, and set up alerts for persistent errors. The [PostEverywhere developer quickstart](/docs/quick-start) includes a production-ready client wrapper with retry logic built in. > **Need higher rate limits?** Every plan includes 60 requests per minute and 1,000 per hour per API key. Talk to us about enterprise limits if you are building an agency tool or SaaS integration. ## What About [Social Media Automation](/social-media-automation) Without Code? Not every team has developers. If you want to automate posting without writing code, PostEverywhere's dashboard includes [auto-scheduling](/social-media-scheduler), [AI caption generation](/ai-content-generator), [cross-posting](/cross-posting), and [bulk scheduling](/social-media-calendar) — all from a visual interface. The API and dashboard work together, so you can mix both approaches. Use the API for programmatic workflows and the dashboard for one-off posts and manual adjustments. ## FAQs ### Do I need a paid plan to use the PostEverywhere API? API access is included on every plan. Every plan, from Lite at $9/mo, includes 60 requests per minute and 1,000 per hour per API key. You can start with the 7-day free trial — cancel anytime — and make API calls immediately. ### Can I post to all 11 platforms in a single API call? Yes. Include all platform names in the `platforms` array and the corresponding account IDs. One request handles Instagram, TikTok, LinkedIn, Facebook, X, YouTube, and Threads simultaneously. ### How do I handle different content formats per platform? You can either send a single `content` field and let the API adapt it per platform, or use the AI generation endpoint to create platform-specific versions. The AI understands character limits, hashtag conventions, and tone differences between platforms. ### Is the API suitable for agencies managing multiple clients? Yes. Each connected account has a unique ID, so you can manage hundreds of client accounts from a single API key. The [multi-account management](/multi-account-management) features work the same way via API as they do in the dashboard. ### What happens if a post fails on one platform but succeeds on others? The API returns per-platform status. A post can be `published` on LinkedIn and `failed` on Instagram. You get the specific error message for the failed platform so you can fix the issue and retry just that one — no need to re-publish everywhere. If writing code against the API is more than you need, an assistant can drive the same publishing through a connector instead. [Nine routes ranked by documented setup steps](/blog/easiest-ai-agents-for-social-media-management) covers the no-code end of this. Building platform by platform instead? The per-network guides like [post to TikTok via API](/blog/post-to-tiktok-api) and [post to YouTube via API](/blog/post-to-youtube-api) cover endpoint-level detail.