Documentation
Guides for the Onepostly API, covering authentication, connecting accounts, publishing and scheduling posts, media uploads, comments, analytics, and webhooks.
Onepostly is one API to publish, schedule and measure across every major social platform. This page takes you from API key to your first post in about five minutes.
The free plan includes one connected account with no credit card required.
Base URL
https://api.onepostly.com
Install An SDK
npm install @onepostly/sdkPrefer raw HTTP? Every example below also shows plain curl, which needs no install at all.
Authentication
All API requests require an API key, passed in the x-api-key header or as an Authorization: Bearer token. The SDKs read it from the ONEPOSTLY_API_KEY environment variable by default.
Get Your API Key
- Sign up or log in. The free plan needs no credit card
- Go to Settings → API Keys
- Click Create
- Copy the key immediately. It is shown only once
Set Up The Client
import { Configuration, ConnectionsApi, PostsApi } from "@onepostly/sdk";
const config = new Configuration({
apiKey: process.env.ONEPOSTLY_API_KEY,
});
const connections = new ConnectionsApi(config);
const posts = new PostsApi(config);Key format op_ prefix. Keys are shown only once at creation. Store them somewhere safe. Use environment variables and create separate keys per app.
Key Concepts
- Connections. Your connected social accounts (X, Instagram, TikTok and more), authorized through OAuth. Every publish targets one or more connections
- Posts. One request creates a post. Each entry in
destinationsreceives its own copy on that platform - Destinations. The per-connection results of a post, each with its own status and external URL
- Media. Images and videos, uploaded through the Media API or referenced from any public HTTPS URL
Every step below returns the ids the next one needs. You get the account id from the list and the post id on create.
Step 1: Connect A Social Account
In Dashboard → Connections, pick a platform and complete the OAuth consent screen. The connection shows up in your dashboard and in the API. Headless connects are available for some platforms. See Connection.
Step 2: List Your Connections
List your connections and grab the id. You pass it as accountId on every publish.
import { Configuration, ConnectionsApi } from "@onepostly/sdk";
const connectionsApi = new ConnectionsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await connectionsApi.listConnections({
limit: 20,
page: 2,
profile: "Business",
platform: "instagram",
addedWithinDays: 90,
sort: "newest",
});
console.log(response);{
"connections": [
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "instagram",
"displayName": "Onepostly",
"handle": "@onepostly",
"avatarUrl": "https://cdn.onepostly.com/avatars/onepostly.jpg",
"status": "active",
"tokenExpiresAt": "2026-10-25T10:00:00.000Z",
"canAutoRenew": true,
"authHealth": "healthy",
"profileName": "Business",
"xSubscriptionType": "Premium",
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
],
"total": 2000,
"page": 1,
"hasMore": true
}Save the account id. The next step targets it.
Step 3: Publish Your First Post
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Ship day",
"mediaUrls": [
"https://cdn.onepostly.com/media/product.jpg"
],
"mediaKind": "image",
"destinations": [
{
"accountId": "YOUR_INSTAGRAM_ACCOUNT_ID"
}
]
},
});
console.log(response);{
"post": {
"id": "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
"text": "Ship day",
"mediaUrls": [
"https://cdn.onepostly.com/media/product.jpg"
],
"mediaKind": "image",
"status": "queued",
"scheduledFor": null,
"timezone": null,
"destinations": [
{
"id": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"status": "draft",
"externalPostId": "17895695668004550",
"externalUrl": "https://www.instagram.com/p/17895695668004550/",
"errorCode": null,
"errorMessage": null,
"publishedAt": "2026-08-25T10:00:00.000Z",
"metrics": null
}
],
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
}The response is 202 Accepted with status queued. Publishing runs in the background. mediaKind is required on every post. Use text for text-only posts. Use image, multi-image, video or stories together with the matching mediaUrls.
Step 4: Confirm It Worked
Poll the post until every destination is published or failed.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.getPost({
id: "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
});
console.log(response);{
"post": {
"id": "b3e1a7c2-8f4d-4e6a-9c1b-2d3e4f5a6b7c",
"text": "Ship day",
"mediaUrls": [
"https://cdn.onepostly.com/media/product.jpg"
],
"mediaKind": "image",
"status": "queued",
"scheduledFor": null,
"timezone": null,
"destinations": [
{
"id": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"status": "draft",
"externalPostId": "17895695668004550",
"externalUrl": "https://www.instagram.com/p/17895695668004550/",
"errorCode": null,
"errorMessage": null,
"publishedAt": "2026-08-25T10:00:00.000Z",
"metrics": null
}
],
"createdAt": "2026-08-25T10:00:00.000Z",
"updatedAt": "2026-08-25T10:00:00.000Z"
}
}Once a destination is published, it carries the live link in externalUrl. Webhooks can push these status changes to you instead of polling.
That's the whole loop. Connect an account, publish and confirm. Everything else is a variation on this.
One Endpoint, Every Posting Mode
The same createPost call covers immediate publishing, scheduling and media.
| You set | Result |
|---|---|
| Nothing extra | Publishes immediately with 202 Accepted and queued |
scheduledFor plus timezone | Publishes automatically at that time with 201 Created and scheduled |
mediaKind plus mediaUrls | Adds media as image, multi-image, video or stories |
And cross-posting is just more entries in the destinations array. Same content, one call, every platform.
await posts.createPost({
createPostBody: {
text: "Cross-posting to all my accounts, right now!",
mediaKind: "text",
destinations: [
{ accountId: "YOUR_X_ACCOUNT_ID" },
{ accountId: "YOUR_INSTAGRAM_ACCOUNT_ID" },
{ accountId: "YOUR_TIKTOK_ACCOUNT_ID", privacyLevel: "PUBLIC_TO_EVERYONE" },
],
},
});Per-platform options like TikTok privacy levels and Pinterest boards are covered in each platform guide.
Beyond Posting
Publishing is the entry point. The same API key and connections open comment moderation, analytics and event-driven updates.
Read Analytics
See how a post performs once its destinations are published. Pass post as described in Analytics.
import { Configuration, AnalyticsApi } from "@onepostly/sdk";
const analyticsApi = new AnalyticsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await analyticsApi.getAnalytics({
post: "1699f415-7fb6-43f4-9d2a-c447491f32a8",
metrics: "views,reach,profile_views",
period: "day",
});
console.log(response);{
"analytics": {
"post": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"status": "ready",
"fetchedAt": "2026-08-25T10:00:00.000Z",
"subjects": [
{
"scope": "destination",
"subjectId": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "instagram",
"externalPostId": "17895695668004550",
"status": "ready",
"metrics": {
"impressions": 1234,
"reach": 987,
"likes": 123,
"comments": 12,
"shares": 4,
"saves": 2,
"plays": 456,
"engagement": 0.14
},
"fetchedAt": "2026-08-25T10:00:00.000Z",
"expiresAt": "2026-09-01T10:00:00.000Z",
"error": null
}
]
}
}Metrics are normalized (likes, comments, shares and so on). Each platform section lists exactly which numbers it returns.
Reply To Comments
List, create and delete comments on published posts. The same endpoints work on every platform that supports them.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.createComment({
createCommentBody: {
"post": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"text": "Love this!",
"parentCommentId": "c0"
},
});
console.log(response);{
"comment": {
"id": "c1",
"text": "Love this!",
"username": "jane_doe",
"likeCount": 12,
"timestamp": "2026-08-25T10:05:00.000Z"
}
}Explore The Rest
Media
Upload images and videos once, reference the URLs everywhere
Webhooks
Real-time publish events instead of polling
MCP Server
Drive Onepostly from Claude and other AI agents
Rate Limits
Quotas, velocity caps, and handling 429s
X bills through a prepaid wallet
Publishing, replying, liking and analytics reads on X debit your Onepostly wallet at X list prices with no markup. Top up in Dashboard → Settings → Billing.
What's Next?
Platform Guides
Publish rules, media limits, and errors per platform
Engagement
Likes, replies, reposts, and comments on published posts
Analytics Freshness
When metrics become available and why they lag
Schedule a Post
Queue content for the perfect moment on every platform
Going to production? Respect rate limits and listen for webhooks instead of polling.