Overview
Quickstart
Publish your first post on a connected account in four steps.
When you finish this page, you have a published post on one of your social accounts and its link on the platform. It takes an API key, one connected account and two API calls.
Create an API Key
Open API Keys in the dashboard and create a key with the read_write permission. Copy it now, because it is shown only once.
export ONEPOSTLY_API_KEY="op_YOUR_KEY"Every sample in these docs reads the key from ONEPOSTLY_API_KEY. See Authentication for headers and permissions.
Install an SDK
npm install @onepostly/sdkPrefer plain HTTP? Skip this step. Every sample has a cURL tab, and the base URL is https://api.onepostly.com.
Connect an Account
Open Connections in the dashboard and sign in to a platform. Your first 2 accounts are free.
Then list your accounts to get their ids.
import { Configuration, AccountsApi } from "@onepostly/sdk";
const accountsApi = new AccountsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await accountsApi.listAccounts();
console.log(response);{
"data": [
{
"id": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "linkedin",
"displayName": "Your Brand",
"handle": "Your Brand",
"avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg",
"status": "active",
"canAutoRenew": false,
"tokenExpiresAt": "2027-05-14T10:00:00.000Z",
"profile": "Default",
"metadata": {},
"createdAt": "2027-03-01T10:00:00.000Z",
"updatedAt": "2027-03-01T10:00:00.000Z"
},
{
"id": "acc_1699f4157fb643f49d2ac447491f3202",
"platform": "x",
"displayName": "Your Brand",
"handle": "yourbrand",
"avatarUrl": "https://cdn.onepostly.com/avatars/yourbrand.jpg",
"status": "active",
"canAutoRenew": true,
"tokenExpiresAt": "2027-05-14T10:00:00.000Z",
"profile": "Default",
"metadata": {},
"xSubscriptionType": "None",
"createdAt": "2027-02-28T10:00:00.000Z",
"updatedAt": "2027-02-28T10:00:00.000Z"
}
],
"nextCursor": null,
"hasMore": false
}You publish to an account by its id, such as acc_1699f4157fb643f49d2ac447491f32a8. Its status must be active.
Publish a Post
Send the text and the account to publish to.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Hello from Onepostly.",
"accounts": [
{
"accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID"
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID",
"platform": "linkedin",
"source": "onepostly",
"status": "publishing",
"text": "Hello from Onepostly.",
"mediaKind": "text",
"media": [],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}You get one post per account in data, each with the status publishing.
| Platform | A post needs |
|---|---|
| X, Facebook, Threads, LinkedIn, Bluesky | Text or media |
| Instagram, TikTok, Pinterest | An image or a video |
| YouTube | A video |
To add media, pass a public file URL in media.
"media": [{ "url": "https://example.com/photo.jpg" }]Posts on X are paid from your wallet, so top it up first.
Check the Result
Read the post by its id.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.getPost({
id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
});
console.log(response);{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_LINKEDIN_ACCOUNT_ID",
"platform": "linkedin",
"source": "onepostly",
"status": "published",
"text": "Hello from Onepostly.",
"mediaKind": "text",
"media": [],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {},
"platformPostId": "urn:li:share:7300123456789012345",
"url": "https://www.linkedin.com/feed/update/urn:li:share:7300123456789012345",
"error": null,
"publishedAt": "2027-03-15T09:00:04.000Z",
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:04.000Z"
}status | Means |
|---|---|
publishing | Still on its way. Read it again shortly |
published | Live, and url links to it on the platform |
failed | Not published, and error says why |
Or subscribe to post.published and post.failed webhooks.
If It Fails
| What you see | Cause | Fix |
|---|---|---|
401 UNAUTHORIZED | The key is missing or deleted | Send the full key |
404 ACCOUNT_NOT_FOUND | Wrong accountId, or it was disconnected | Copy it from GET /v1/accounts |
400 VALIDATION_ERROR | A wrong field, named in param | Fix it, or add media |
402 INSUFFICIENT_WALLET | The X wallet is too low | Top up in Settings → Wallet |
402 USAGE_BILLING_REQUIRED | A 3rd account with no card | Add one in Settings → Billing |
status is failed | The platform refused it | Read error.code, then post again |
Send support the error's requestId. All codes are in Errors.
Next Steps
Create Posts
Cross-post, set options per account and list your posts.
Media
Upload your own images and videos.
Scheduling and Editing
Publish later, edit or cancel a scheduled post.
Webhooks
Get notified when a post is published or fails.
Connect Accounts
Connect accounts in the dashboard, or let your users connect theirs.
Compare Platforms
What each platform supports and how to connect it.