Posting API
A social media posting API for ten networks
Publish text, images and video to X, Instagram, Facebook, LinkedIn, TikTok, YouTube, Threads, Pinterest, Bluesky and Google Business with one request. postpeg checks the post against each network, publishes it through their official APIs, and reports back per account, so your product gets one integration instead of ten.
How a post goes out
- Connect accounts. Your users approve access on each network’s own screen through a hosted OAuth link (Bluesky uses an app password). You get back an account id; postpeg keeps the tokens.
- Send one request.
POST /v1/postswith up to 50account_idson any mix of networks, thecontent, up to 20mediaitems by public https URL, and anyplatform_optionsa network needs. - It’s checked first. Every network’s rules run before anything is stored or sent. If one account’s network would refuse the post, nothing is published anywhere, and the
400lists every problem at once. - Each account is published separately. Each one is a target with its own status,
urlanderror, so one network having a bad minute never holds up the rest.
Read the result with GET /v1/posts/{id}: the post is published when every target is live, or partially_published when some failed, with the reason on each failed target.
Every network’s rules, before sending
Text limits run from 280 characters on X to 63,206 on Facebook, counted as people see characters (an emoji is one). Media is required on Instagram, TikTok, YouTube and Pinterest; TikTok and YouTube take video only. YouTube needs a title and Pinterest a board_id in platform_options.
You don’t have to keep track of any of that. Send the post and postpeg answers with the exact field to fix, like content being over X’s limit or media missing a video for TikTok. The platform reference has every number, generated from the same definitions the API validates against.
When something goes wrong
A network that times out, rate-limits or has an outage is retried: up to 5 attempts, waiting 2, 4, 8 and 16 minutes, or longer if the network asks. A refusal that won’t change on retry fails at once, with the network’s reason in error.
If a publish is interrupted after the request may have reached the network, the target is marked failed rather than retried: a duplicate post is worse than a missing one. For the same reason, send an Idempotency-Key header, and a retry on your side returns the original post instead of creating a second.
When a network expires a login, the account turns reconnect_required and you can send its owner a new connect link.
Example: publish now to three networks
Leave out scheduled_at and the post is queued straight away. The response comes back before the networks answer, with each target queued.
curl https://api.postpeg.com/v1/posts \
-H "Authorization: Bearer $POSTPEG_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: changelog-2026-10-01" \
-d '{
"account_ids": [
"acc_mfz1x0k27d4q8vbn3c5s0a1p9e",
"acc_mfz1y4r9h2c6t0wqk8e3m7ld5f",
"acc_mfz20b5n1s8f4j7xv2p9r6hu1c"
],
"content": "Scheduled posts now retry on their own when a network has a bad minute. Changelog: https://example.com/changelog #buildinpublic",
"media": [
{
"url": "https://example.com/changelog.png",
"type": "image"
}
]
}'{
"id": "post_mfz2k3v8q1w5e9r4t7y0u2i6o3",
"content": "Scheduled posts now retry on their own when a network has a bad minute. Changelog: https://example.com/changelog #buildinpublic",
"media": [
{
"url": "https://example.com/changelog.png",
"type": "image"
}
],
"platform_options": {},
"status": "publishing",
"scheduled_at": null,
"targets": [
{
"account_id": "acc_mfz1x0k27d4q8vbn3c5s0a1p9e",
"platform": "x",
"status": "queued",
"platform_post_id": null,
"url": null,
"error": null,
"attempts": 0,
"published_at": null
},
{
"account_id": "acc_mfz1y4r9h2c6t0wqk8e3m7ld5f",
"platform": "linkedin",
"status": "queued",
"platform_post_id": null,
"url": null,
"error": null,
"attempts": 0,
"published_at": null
},
{
"account_id": "acc_mfz20b5n1s8f4j7xv2p9r6hu1c",
"platform": "instagram",
"status": "queued",
"platform_post_id": null,
"url": null,
"error": null,
"attempts": 0,
"published_at": null
}
],
"created_at": "2026-09-24T14:02:11.418Z"
}Questions
- How many accounts can one post go to?
- Up to 50
account_idsper request, on any mix of the ten networks. How many accounts you can connect depends on the plan: Starter $29 (10 connected accounts), Pro $79 (50 connected accounts), Scale $199 (unlimited connected accounts). - Do I handle OAuth tokens for each network?
- No. Accounts connect through a hosted flow: you ask for a link, the owner approves on the network’s own screen, and postpeg keeps the tokens. Your code only deals with account ids.
- What if a post publishes on some networks but not others?
- The post’s status becomes
partially_published. Each target keeps its own status, so the live ones have aurland the failed ones have anerrorsaying why. - Can I call it from a script or an agent?
- Yes. postpeg is a plain REST API with JSON bodies and a bearer key, so it works from any HTTP client or agent that can call a REST API.
The rest of the API
- Scheduling APIPass scheduled_at up to a year ahead. Posts go out within a minute of their time, and can be cancelled until they do.
- Analytics APIImpressions, reach, likes, shares and follower growth per post and per account, with null where a network doesn’t report a number.
- Comments APIList the comments on posts you published, reply to them, and hide the ones you don’t want shown.
- Instagram DM APIRead direct-message conversations and reply to people who wrote first, within the 24-hour window.
Send your first post in a few minutes
The 7-day trial has every feature and 3 connected accounts, with no card. The quickstart takes you from a key to a published post.