The social media API for developers & agents
Publish and schedule to X, LinkedIn, Instagram and Facebook with one request. Call it from your backend, or let your AI agent call it over MCP.
20 free credits a month. No card needed.
Sandbox today: posts are simulated until live platform access opens.
- X
- More coming soon
One request in. A result for every platform out.
BetterPost checks each platform's rules, publishes to every account you list and tells you exactly which ones worked. If one platform fails, the others still go out.
{
"content": "Launch day.",
"platforms": [
{ "platform": "twitter", … },
{ "platform": "linkedin", … },
{ "platform": "instagram", … },
{ "platform": "facebook", … }
],
"publishNow": true
}- XPublished5 credits
- LinkedInPublished1 credit
- InstagramPublished1 credit
- FacebookPublished1 credit
This request returns 202 Accepted and costs 8 credits, charged once when the post is accepted. Failed platforms are refunded.
The calls you will actually make
Requests and responses in the exact shape the API uses. Copy one, swap in your key and account IDs, and run it against the sandbox.
Send one post to any mix of connected accounts. You get a result per platform in the same response, and a retried request with the same idempotency key never posts twice.
curl -X POST https://api.betterpost.dev/v1/posts \
-H "x-access-key: sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Our changelog for October is live.",
"platforms": [
{
"platform": "twitter",
"accountId": "acc_8k2mx4p1q7r3s9t0v5w6y2"
},
{
"platform": "linkedin",
"accountId": "acc_3fq9l2n6b8d0h4j7k1m5c3"
}
],
"publishNow": true,
"idempotencyKey": "changelog-2026-10"
}'HTTP/1.1 202 Accepted
x-betterpost-mode: sandbox
{
"success": true,
"status": "published",
"postId": "post_7h3kq2m9x0c4v8b1n5z6l2pa",
"platforms": [
{
"platform": "twitter",
"accountId": "acc_8k2mx4p1q7r3s9t0v5w6y2",
"success": true,
"platformPostUrl": "https://betterpost.dev/sandbox/p/twitter/sbx_1849202751938204617"
},
{
"platform": "linkedin",
"accountId": "acc_3fq9l2n6b8d0h4j7k1m5c3",
"success": true,
"platformPostUrl": "https://betterpost.dev/sandbox/p/linkedin/sbx_7302948115602843390"
}
]
}Pass a local time and an IANA timezone. BetterPost stores it in UTC, reserves the credits up front and publishes on the minute.
curl -X POST https://api.betterpost.dev/v1/posts \
-H "x-access-key: sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Doors open at 9. See you there.",
"platforms": [
{
"platform": "instagram",
"accountId": "acc_5t1ri9e3w7q2z6x0c4v8b1"
},
{
"platform": "facebook",
"accountId": "acc_9w4ef6g8h0j2k4l6m8n0p2"
}
],
"mediaItems": [
{
"type": "image",
"url": "https://assets.betterpost.dev/m/launch.jpg"
}
],
"scheduledFor": "2026-11-03T09:00:00",
"timezone": "America/New_York"
}'HTTP/1.1 202 Accepted
{
"success": true,
"status": "scheduled",
"postId": "post_q8w2e4r6t1y3u5i7o9p0a2sd",
"scheduledFor": "2026-11-03T14:00:00.000Z",
"platforms": [
{ "platform": "instagram", "accountId": "acc_5t1ri9e3w7q2z6x0c4v8b1", "success": true },
{ "platform": "facebook", "accountId": "acc_9w4ef6g8h0j2k4l6m8n0p2", "success": true }
]
}Get a signed event when a post publishes, partly fails or fails, and when an account needs reconnecting. Failed deliveries are retried twice.
POST /hooks/betterpost HTTP/1.1
Host: your-app.example.com
Content-Type: application/json
User-Agent: BetterPost-Webhooks/1.0
X-BetterPost-Event-Id: evt_m2n4b6v8c0x1z3l5k7j9h2gf
X-BetterPost-Event-Type: post.partial
X-BetterPost-Timestamp: 1793714403
X-BetterPost-Signature: sha256=<hex HMAC of "1793714403.<raw body>">
{
"version": "2026-10-21",
"id": "evt_m2n4b6v8c0x1z3l5k7j9h2gf",
"type": "post.partial",
"createdAt": "2026-11-03T14:00:03.000Z",
"projectId": "proj_d4f6h8j0k2l4z6x8c0v2b4n6",
"profileId": null,
"data": {
"post": {
"id": "post_q8w2e4r6t1y3u5i7o9p0a2sd",
"status": "partial",
"content": "Doors open at 9. See you there.",
"scheduledFor": "2026-11-03T14:00:00.000Z",
"publishedAt": "2026-11-03T14:00:01.000Z",
"mediaItems": [
{
"type": "image",
"url": "https://assets.betterpost.dev/m/launch.jpg",
"thumbnail": null,
"filename": "launch.jpg",
"size": 184320,
"mimeType": "image/jpeg"
}
],
"links": {
"betterpost": "https://betterpost.dev/dashboard/posts/post_q8w2e4r6t1y3u5i7o9p0a2sd",
"api": "https://api.betterpost.dev/v1/posts/post_q8w2e4r6t1y3u5i7o9p0a2sd"
}
},
"platforms": [
{
"platform": "instagram",
"integrationId": "acc_5t1ri9e3w7q2z6x0c4v8b1",
"profileId": "prof_a1s3d5f7g9h2j4k6l8z0x2c4",
"status": "published",
"platformPostId": "sbx_5520193847561029384",
"platformPostUrl": "https://betterpost.dev/sandbox/p/instagram/sbx_5520193847561029384",
"publishedAt": "2026-11-03T14:00:01.000Z",
"errorMessage": null,
"warningMessage": null
},
{
"platform": "facebook",
"integrationId": "acc_9w4ef6g8h0j2k4l6m8n0p2",
"profileId": "prof_a1s3d5f7g9h2j4k6l8z0x2c4",
"status": "failed",
"platformPostId": null,
"platformPostUrl": null,
"publishedAt": null,
"errorMessage": "Account is disconnected",
"warningMessage": null
}
]
}
}import { createHmac, timingSafeEqual } from "node:crypto";
// Sign "<timestamp>.<raw body>" with your webhook secret.
export function verify(rawBody, headers, secret) {
const ts = headers["x-betterpost-timestamp"];
const expected = "sha256=" +
createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const given = headers["x-betterpost-signature"] ?? "";
return given.length === expected.length &&
timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}Add the MCP server to Claude, Cursor or Codex and your agent can list accounts, create posts and check results with the same rules as the REST API.
{
"mcpServers": {
"betterpost": {
"url": "https://mcp.betterpost.dev/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}You: Post "We just shipped dark mode" to our X and LinkedIn
accounts tomorrow at 10am Berlin time.
Agent → list_accounts {}
Agent → create_post {
"content": "We just shipped dark mode",
"platforms": [
{
"platform": "twitter",
"accountId": "acc_8k2mx4p1q7r3s9t0v5w6y2"
},
{
"platform": "linkedin",
"accountId": "acc_3fq9l2n6b8d0h4j7k1m5c3"
}
],
"scheduledFor": "2026-10-23T10:00:00",
"timezone": "Europe/Berlin"
}
Agent: Scheduled for Oct 23, 10:00 (Europe/Berlin) on X and LinkedIn.
It will use 6 credits.From sign-up to first post in three steps
Create a free account
Sign in with email, Google or GitHub. Your first project and a sandbox API key are ready straight away.
Connect an account
Send your user to the connect URL. They approve access once and you get an account ID to post with.
Send your first post
POST to /v1/posts with the account IDs. Check the per-platform results, or wait for the webhook.
The parts you would rather not build yourself
Multi-platform publishing
Text, images and video to X, LinkedIn, Instagram and Facebook, with per-platform text when you need it.
Scheduling
Schedule in any timezone, then reschedule, edit or cancel. Cancelling refunds the credits.
Signed webhooks
HMAC-signed events for published, partial and failed posts and for accounts that need reconnecting.
Managed OAuth
We host the connect flow and keep the tokens. You store an account ID, nothing else.
Profiles for every customer
Group accounts into profiles, one per brand or end user, and connect as many as you need.
Idempotency and partial failures
Retries with the same key return the original post. One failing platform never blocks the rest.
MCP server
A hosted MCP endpoint with tools for accounts, posts, scheduling, media and usage.
Docs written for developers
Every endpoint with a cURL example, every error with a plain message, and llms.txt for your agent.
Built for AI agents too
Point Claude, Cursor or Codex at the BetterPost MCP server with your API key. The agent gets tools with clear descriptions, the same validation and credit rules as the REST API, and plain-language errors it can act on.
Tools your agent can call
- list_accounts
- create_post
- get_post
- list_scheduled_posts
- reschedule_post
- upload_media_from_url
- get_usage
- and more
{
"mcpServers": {
"betterpost": {
"url": "https://mcp.betterpost.dev/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Add to .cursor/mcp.json in your project, or ~/.cursor/mcp.json for all projects.
Endpoint https://mcp.betterpost.dev/mcp
Questions, answered
Can I post to real accounts today?
What does the sandbox simulate?
How do credits work?
What happens if one platform fails?
How do I avoid double posts when my request times out?
Is there a rate limit?
Can I connect accounts on behalf of my users?
Which AI tools work with the MCP server?
Do I need a card to start?
Send your first post today
Start in the sandbox with 20 free credits a month. Your code keeps working when live posting opens for each platform.